Крестоплатформенная реализация библиотеки C ++ 17 для универсально уникальных идентификаторов , просто знаете как UUID или GUID (в основном на Windows). UUID-это 128-разрядное число, используемое для однозначного идентификации информации в компьютерных системах, таких как клавиши таблицы баз данных, интерфейсы COM, классы и библиотеки типов и многие другие.
Для получения информации о UUID/GUID см.:
Хотя спецификация помещает библиотеку UUID в пространство имен std , эта реализация использует пространство имен uuids для этой цели, чтобы библиотека использовалась, не нарушая ограничения, налагаемые на пространство имен std . Доступны следующие типы и утилиты:
Основные типы:
| Имя | Описание |
|---|---|
uuid | класс, представляющий UUID; Это может быть построено по умолчанию (nil uuid), построенное из диапазона (определено парой итераторов) или из span . |
uuid_variant | прочный перевод, представляющий тип UUID |
uuid_version | Регистральный перевод, представляющий версию UUID |
Генераторы:
| Имя | Описание |
|---|---|
basic_uuid_random_generator | Функциональный объект, который генерирует Uuids версии 4 с использованием генератора псевдолудочного генератора. |
uuid_random_generator | A basic_uuid_random_generator с использованием двигателя Mersenne Twister ( basic_uuid_random_generator<std::mt19937> ) |
uuid_name_generator | Функциональный объект, который генерирует версию 5, на основе имени UUID с использованием хэширования SHA1. |
uuid_system_generator | Функциональный объект, который генерирует новые UUID с использованием ресурсов операционной системы ( CoCreateGuid в Windows, uuid_generate на Linux, CFUUIDCreate на Mac)Примечание : это не является частью стандартного предложения. Он доступен только в том случае, если определен макрос UUID_SYSTEM_GENERATOR . |
uuid_time_generator | Экспериментальная функция объекта, который генерирует UUIDS на основе времени. Примечание . Это экспериментальная функция и не должна использоваться ни в каком производственном коде. Он доступен только в том случае, если определен макрос UUID_TIME_GENERATOR . |
Утилиты:
| Имя | Описание |
|---|---|
std::swap<> | Специализация swap на uuid |
std::hash<> | Специализация hash для uuid (необходимо для хранения UUID в неупорядоченных ассоциативных контейнерах, таких как std::unordered_set ) |
Константы:
| Имя | Описание |
|---|---|
uuid_namespace_dns | Идентификатор пространства имен для UUIDS на основе имени, когда String String-это полностью квалифицированное доменное имя. |
uuid_namespace_url | Идентификатор пространства имен для UUIDS на основе имени, когда String String-URL. |
uuid_namespace_oid | Идентификатор пространства имен для UUIDS на основе имени, когда MAME String является ISO OID (см. Https://odref.com/, https://en.wikipedia.org/wiki/object_identifier). |
uuid_namespace_x500 | Идентификатор пространства имен для UUIDS на основе имени, когда name String составляет X.500 DN, в DER или формат вывода текста (см. Https://en.wikipedia.org/wiki/x.500, https://en.wikipedia.org/wiki/abstract_syntax_notation_one). |
Другой:
| Имя | Описание |
|---|---|
operator== и operator!= | Для сравнения UUIDS для равенства/неравенства |
operator< | Для сравнения, является ли один Uuids меньше, чем другой. Хотя эта операция не имеет большого логического смысла, это необходимо для хранения UUID в STD :: SET. |
operator<< | написать UUID в выходной поток, используя каноническое текстовое представление. |
to_string() | Создает строку с каноническим текстовым представлением UUID. |
Эта библиотека является реализацией предложения P0959.
Поскольку предложение развивается на основе стандартного комитета и обратной связи сообщества C ++, эта реализация библиотеки будет отражать эти изменения.
См. Историю пересмотра предложения по истории изменений.
Ниже приведен список примеров использования библиотеки:
Создание ноль UUID
uuid empty;
assert (empty.is_nil());Создание нового UUID
uuid const id = uuids::uuid_system_generator{}();
assert (!id.is_nil());
assert (id.version() == uuids::uuid_version::random_number_based);
assert (id.variant() == uuids::uuid_variant::rfc);Создание нового UUID со случайным генератором по умолчанию
std::random_device rd;
auto seed_data = std::array< int , std::mt19937::state_size> {};
std::generate (std::begin(seed_data), std::end(seed_data), std::ref(rd));
std::seed_seq seq (std::begin(seed_data), std::end(seed_data));
std::mt19937 generator (seq);
uuids::uuid_random_generator gen{generator};
uuid const id = gen();
assert (!id.is_nil());
assert (id.as_bytes().size() == 16);
assert (id.version() == uuids::uuid_version::random_number_based);
assert (id.variant() == uuids::uuid_variant::rfc);Создание нового UUID с определенным случайным генератором
std::random_device rd;
auto seed_data = std::array< int , 6 > {};
std::generate (std::begin(seed_data), std::end(seed_data), std::ref(rd));
std::seed_seq seq (std::begin(seed_data), std::end(seed_data));
std::ranlux48_base generator (seq);
uuids::basic_uuid_random_generator<std::ranlux48_base> gen (&generator);
uuid const id = gen();
assert (!id.is_nil());
assert (id.as_bytes().size() == 16);
assert (id.version() == uuids::uuid_version::random_number_based);
assert (id.variant() == uuids::uuid_variant::rfc);Создание нового UUID с генератором имени
uuids::uuid_name_generator gen (uuids::uuid::from_string( " 47183823-2574-4bfd-b411-99ed177d3e43 " ).value());
uuid const id = gen( " john " );
assert (!id.is_nil());
assert (id.version() == uuids::uuid_version::name_based_sha1);
assert (id.variant() == uuids::uuid_variant::rfc);Создать UUID из строки
auto str = " 47183823-2574-4bfd-b411-99ed177d3e43 " s;
auto id = uuids::uuid::from_string(str);
assert (id.has_value());
assert (uuids::to_string(id.value()) == str);
// or
auto str = L" 47183823-2574-4bfd-b411-99ed177d3e43 " s;
uuid id = uuids::uuid::from_string(str).value();
assert (uuids::to_string< wchar_t >(id) == str);Создание UUID из последовательности из 16 байтов
std::array<uuids::uuid::value_type, 16 > arr{{
0x47 , 0x18 , 0x38 , 0x23 ,
0x25 , 0x74 ,
0x4b , 0xfd ,
0xb4 , 0x11 ,
0x99 , 0xed , 0x17 , 0x7d , 0x3e , 0x43 }};
uuid id (arr);
assert (uuids::to_string(id) == "47183823-2574-4bfd-b411-99ed177d3e43");
// or
uuids::uuid::value_type arr[ 16 ] = {
0x47 , 0x18 , 0x38 , 0x23 ,
0x25 , 0x74 ,
0x4b , 0xfd ,
0xb4 , 0x11 ,
0x99 , 0xed , 0x17 , 0x7d , 0x3e , 0x43 };
uuid id (std::begin(arr), std::end(arr));
assert (uuids::to_string(id) == "47183823-2574-4bfd-b411-99ed177d3e43");
// or
uuids::uuid id{{
0x47 , 0x18 , 0x38 , 0x23 ,
0x25 , 0x74 ,
0x4b , 0xfd ,
0xb4 , 0x11 ,
0x99 , 0xed , 0x17 , 0x7d , 0x3e , 0x43 }};
assert (uuids::to_string(id) == "47183823-2574-4bfd-b411-99ed177d3e43");Сравнивая Uuids
uuid empty;
uuid id = uuids::uuid_system_generator{}();
assert (empty == empty);
assert (id == id);
assert (empty != id);Обмен UUIDS
uuid empty;
uuid id = uuids::uuid_system_generator{}();
assert (empty.is_nil());
assert (!id.is_nil());
std::swap (empty, id);
assert (!empty.is_nil());
assert (id.is_nil());
empty.swap(id);
assert (empty.is_nil());
assert (!id.is_nil());Преобразование в строку
uuid empty;
assert (uuids::to_string(empty) == "00000000-0000-0000-0000-000000000000");
assert (uuids::to_string< wchar_t >(empty) == L"00000000-0000-0000-0000-000000000000");Использование с помощью заказанного ассоциативного контейнера
std::random_device rd;
auto seed_data = std::array< int , std::mt19937::state_size> {};
std::generate (std::begin(seed_data), std::end(seed_data), std::ref(rd));
std::seed_seq seq (std::begin(seed_data), std::end(seed_data));
std::mt19937 engine (seq);
uuids::uuid_random_generator gen (&engine);
std::set<uuids::uuid> ids{uuid{}, gen (), gen (), gen (), gen ()};
assert (ids.size() == 5);
assert (ids.find(uuid{}) != ids.end());Использование в неупорядоченном ассоциативном контейнере
std::random_device rd;
auto seed_data = std::array< int , std::mt19937::state_size> {};
std::generate (std::begin(seed_data), std::end(seed_data), std::ref(rd));
std::seed_seq seq (std::begin(seed_data), std::end(seed_data));
std::mt19937 engine (seq);
uuids::uuid_random_generator gen (&engine);
std::unordered_set<uuids::uuid> ids{uuid{}, gen (), gen (), gen (), gen ()};
assert (ids.size() == 5);
assert (ids.find(uuid{}) != ids.end());Хэширование Uuids
using namespace std ::string_literals ;
auto str = " 47183823-2574-4bfd-b411-99ed177d3e43 " s;
uuid id = uuids::uuid::from_string(str).value();
auto h1 = std::hash<std::string>{};
auto h2 = std::hash<uuid>{};
assert (h1(str) == h2(id)); Если вы генерируете UUID, используя basic_uuid_random_generator и std :: random_device, чтобы заселить генератор, имейте в виду, что это не может быть неэнергинизма и фактически генерирует одну и ту же последовательность чисел:
std :: random_device может быть реализован в терминах, определяемом реализацией двигателя псевдолудочного номера, если не определенного источника (например, аппаратное устройство) недоступен для реализации. В этом случае каждый объект std :: random_device может генерировать одинаковую последовательность чисел.
Это может быть проблемой с Mingw. См. Ошибка 85494 - Реализация random_device на Mingw бесполезна. Это было зафиксировано в GCC 9.2.
Портативная альтернатива - использовать библиотеку Boost.Random.
Библиотека поддерживается во всех основных операционных системах: ОС Windows, Linux и Mac.
Если вы используете библиотеку в проекте, созданном с C ++ 20, то вы можете использовать std::span . Это используется по умолчанию, если заголовок поддерживается вашим компилятором. Проверка выполняется с макросом функционального тестирования __CPP_LIB_SPAN.
В противном случае, например, при строительстве с C ++ 17, std::span недоступен. Тем не менее, библиотека поддержки Microsoft Руководства (AKA GSL) может использоваться для его реализации span (из которой была определена стандартная версия). Библиотека Stduuid по умолчанию использует эту реализацию, если std::span недоступен.
Чтобы обеспечить использование gsl::span , убедитесь, что библиотека GSL доступна, а каталог GSL включает в себя в каталогах include для проекта.
Если вы используете Cmake для создания тестового проекта, убедитесь, что переменная, называемая UUID_USING_CXX20_SPAN не определена, или ее значение OFF (это значение по умолчанию). Это гарантирует, что каталог gsl будет включен в список поисковых каталогов.
Проект тестирования доступен в источниках. Чтобы построить и выполнить тесты, выполните следующее:
build в корневом каталоге источниковcmake .. из каталога build ; Если у вас нет Cmake, вы должны сначала установить его.Примеры
Чтобы сгенерировать файлы проекта для Visual Studio 2019, вы можете запустить следующие команды:
cd build
cmake -G "Visual Studio 17" -A x64 ..
Чтобы включить генератор операционной системы UUID, установите переменную UUID_SYSTEM_GENERATOR на ON .
cd build
cmake -G "Visual Studio 17" -A x64 -DUUID_SYSTEM_GENERATOR=ON ..
Чтобы включить экспериментальный генератор, основанный на времени, установите переменную UUID_TIME_GENERATOR на ON .
cd build
cmake -G "Visual Studio 17" -A x64 -DUUID_TIME_GENERATOR=ON ..
Реализация SHA1 основана на библиотеке Tinysha1.