Проверьте, является ли std :: string действительным uuid, используя boost

Я хочу проверить, является ли данная строка действительным UUID, используя boost.

Вот что я придумал, посмотрев документацию на сайте Boost:

void validate_uuid(const std::string& value)
{
try
{
boost::uuids::string_generator stringGenerator;
(void)stringGenerator(value);
}

catch (const std::exception& ex)
{
// ...
}
}

Однако это не всегда работает.

Если я вызываю функцию со строкой, которая слишком коротка для действительного UUID, исключение выдается, как и ожидалось. Но если я вызываю функцию с неверным UUID (например, 00000000-0000-0000-0000-00000000000K) не исключение не выбрасывается.

Пожалуйста, кто-нибудь может уточнить, почему это происходит.

Кроме того, я видел использование boost :: lexical_cast для чтения строки как UUID, как опубликовано Вот. Мне интересно, должен ли я следовать этому подходу. Любой совет приветствуется.

6

Решение

Код, который вы имели, ничего не делает с точки зрения проверки. Вместо этого он генерирует UUID на основе переданной константы (как хеш-функция).

Присмотревшись, я ошибся. Похоже, отсутствующий бит проверки является проверкой версии:

Жить на Колиру

#include <boost/uuid/uuid.hpp>
#include <boost/uuid/uuid_io.hpp>
#include <boost/uuid/string_generator.hpp>
#include <iostream>

bool is_valid_uuid(std::string const& maybe_uuid, boost::uuids::uuid& result) {
using namespace boost::uuids;

try {
result = string_generator()(maybe_uuid);
return result.version() != uuid::version_unknown;
} catch(...) {
return false;
}
}

int main() {
std::string maybe_uuid;
std::cout << "Enter a UUID: ";

while (std::cin >> maybe_uuid)
{
boost::uuids::uuid result;
bool is_valid = is_valid_uuid(maybe_uuid, result);
std::cout << "\n'" << maybe_uuid << "' valid: " << std::boolalpha << is_valid << "\n";

if (is_valid)
std::cout << "Parsed value: " << result << "\n";
}
}

Пример вывода из Coliru: echo 00000000-0000-{0,4}000-0000-000000000000 $(uuidgen) "{$(uuidgen)}" | ./a.out:

Enter a UUID:
'00000000-0000-0000-0000-000000000000' valid: false

'00000000-0000-4000-0000-000000000000' valid: true
Parsed value: 00000000-0000-4000-0000-000000000000

'a2c59f5c-6c9b-4800-afb8-282fc5e743cc' valid: true
Parsed value: a2c59f5c-6c9b-4800-afb8-282fc5e743cc

'{82a31d37-6fe4-4b80-b608-c63ec5ecd578}' valid: true
Parsed value: 82a31d37-6fe4-4b80-b608-c63ec5ecd578
2

Другие решения

Поскольку вы уже используете boost, вы можете использовать регулярные выражения, чтобы проверить, является ли ваша строка действительным UUID

Например, для UUID версии 4 вы можете использовать следующий код

bool validate_uuid(const std::string& s)
{
static const boost::regex e("[a-f0-9]{8}-[a-f0-9]{4}-4[a-f0-9]{3}-[89aAbB][a-f0-9]{3}-[a-f0-9]{12}");
return regex_match(s, e); // note: case sensitive now
}

(Как уже упоминалось в этом ответ и в вики должна быть действительная цифра версии и другая «специальная» цифра).

Жить на колиру.

4

Это кажется намного проще:

#include <boost/uuid/uuid.hpp>
#include <boost/uuid/uuid_io.hpp>
#include <iostream>
#include <sstream>

int main()
{
std::string t1("01234567-89ab-cdef-0123-456789abcdef");
std::string t2("Test UUID");

boost::uuids::uuid u;
std::istringstream iss(t1);
iss >> u;
if (iss.good())
std::cerr << "'" << t1 << "' is a good UUID\n";
else
std::cerr << "'" << t1 << "' is not a good UUID\n";

iss.str(t2);
iss >> u;
if (iss.good())
std::cerr << "'" << t2 << "' is a good UUID\n";
else
std::cerr << "'" << t2 << "' is not a good UUID\n";

return 0;
}

$ g++ -I/usr/local/include -std=c++11 test1.cpp
$ a.out
'01234567-89ab-cdef-0123-456789abcdef' is a good UUID
'Test UUID' is not a good UUID
2