Verified Commit 2e792a62 authored by Artem Klevtsov's avatar Artem Klevtsov 😹

Add validate UUIDs

parent c62502b7
......@@ -3,5 +3,6 @@
export(uuid_generate_name)
export(uuid_generate_nil)
export(uuid_generate_random)
export(uuid_validate)
importFrom(Rcpp,sourceCpp)
useDynLib(RcppUUID, .registration = TRUE)
# Generated by using Rcpp::compileAttributes() -> do not edit by hand
# Generator token: 10BE3573-1514-4C36-9D1C-5A225CD40393
#' @rdname uuid_generate
#' @rdname uuid
#' @export
uuid_generate_random <- function(n = 1L) {
.Call(`_RcppUUID_uuid_generate_random`, n)
}
#' @rdname uuid_generate
#' @rdname uuid
#' @export
uuid_generate_nil <- function(n = 1L) {
.Call(`_RcppUUID_uuid_generate_nil`, n)
}
#' @rdname uuid_generate
#' @rdname uuid
#' @export
uuid_generate_name <- function(x) {
.Call(`_RcppUUID_uuid_generate_name`, x)
}
#' @rdname uuid
#' @export
uuid_validate <- function(x) {
.Call(`_RcppUUID_uuid_validate`, x)
}
......@@ -10,7 +10,7 @@
#'
#' @return Character vector with UUIDs.
#'
#' @name uuid_generate
#' @name uuid
#'
#' @examples
#' # generate random UUIDs
......@@ -19,5 +19,10 @@
#' uuid_generate_nil(2)
#' # generate name UUIDs
#' uuid_generate_name(c("one", "two"))
#' # validate UUIDs
#' uuid_validate(uuid_generate_random(2))
#' uuid_validate(uuid_generate_nil(2))
#' uuid_validate(uuid_generate_name(c("one", "two")))
#' uuid_validate(c("a", ""))
#'
NULL
# regex pattern to validate
ptrn <- "[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}"
uuid_ptrn <- "[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}"
uuid_nil <- "00000000-0000-0000-0000-000000000000"
# test uuid_generate_random
# test uuid_generate_random -----------------------------------------------
expect_error(uuid_generate_random(NULL))
expect_error(uuid_generate_random(integer(0)))
# expect_error(uuid_generate_random(NA_integer_))
expect_error(uuid_generate_random(c(0, 0)))
expect_equal(uuid_generate_random(0), character(0))
expect_true(is.character(uuid_generate_random(1)))
expect_true(grepl(ptrn, uuid_generate_random(1)))
expect_true(grepl(uuid_ptrn, uuid_generate_random(1)))
expect_equal(length(uuid_generate_random(1)), 1)
expect_equal(length(uuid_generate_random(5)), 5)
expect_equal(length(unique(uuid_generate_random(1000))), 1000)
# uuid_generate_nil
# uuid_generate_nil -------------------------------------------------------
expect_error(uuid_generate_nil(NULL))
expect_error(uuid_generate_nil(integer(0)))
# expect_error(uuid_generate_nil(NA_integer_))
expect_error(uuid_generate_nil(c(0, 0)))
expect_equal(uuid_generate_nil(0), character(0))
expect_true(grepl(ptrn, uuid_generate_nil(1)))
expect_true(grepl(uuid_ptrn, uuid_generate_nil(1)))
expect_true(is.character(uuid_generate_nil(1)))
expect_equal(uuid_generate_nil(1), "00000000-0000-0000-0000-000000000000")
expect_equal(uuid_generate_nil(1), uuid_nil)
expect_equal(length(unique(uuid_generate_nil(100))), 1)
# test uuid_generate_name
# test uuid_generate_name -------------------------------------------------
expect_error(uuid_generate_name(NULL))
expect_error(uuid_generate_name(NA_integer_))
expect_error(uuid_generate_name(c(0, 0)))
expect_equal(uuid_generate_name(character(0)), character(0))
expect_true(grepl(ptrn, uuid_generate_name("a")))
expect_equal(uuid_generate_name(""), "00000000-0000-0000-0000-000000000000")
expect_true(grepl(uuid_ptrn, uuid_generate_name("a")))
expect_equal(uuid_generate_name(""), uuid_nil)
expect_equal(length(uuid_generate_name(letters)), length(letters))
expect_equal(length(unique(uuid_generate_name(letters))), length(letters))
# test uuid_validate ------------------------------------------------------
expect_error(uuid_validate(NULL))
expect_error(uuid_validate(NA_integer_))
expect_error(uuid_validate(c(0, 0)))
expect_equal(uuid_validate(character(0)), logical(0))
expect_true(uuid_validate(uuid_generate_random(1)))
expect_true(uuid_validate(uuid_generate_nil(1)))
expect_true(uuid_validate(uuid_generate_name("a")))
expect_false(uuid_validate("a"))
expect_equal(length(uuid_validate(c("a", "f"))), 2)
expect_equal(length(uuid_validate(uuid_generate_random(10))), 10)
......@@ -4,7 +4,8 @@
\alias{uuid_generate_random}
\alias{uuid_generate_nil}
\alias{uuid_generate_name}
\alias{uuid_generate}
\alias{uuid_validate}
\alias{uuid}
\title{Generate UUIDs}
\usage{
uuid_generate_random(n = 1L)
......@@ -12,6 +13,8 @@ uuid_generate_random(n = 1L)
uuid_generate_nil(n = 1L)
uuid_generate_name(x)
uuid_validate(x)
}
\arguments{
\item{n}{Number of generated UUIDs.}
......@@ -32,5 +35,10 @@ uuid_generate_random(2)
uuid_generate_nil(2)
# generate name UUIDs
uuid_generate_name(c("one", "two"))
# validate UUIDs
uuid_validate(uuid_generate_random(2))
uuid_validate(uuid_generate_nil(2))
uuid_validate(uuid_generate_name(c("one", "two")))
uuid_validate(c("a", ""))
}
......@@ -35,11 +35,22 @@ BEGIN_RCPP
return rcpp_result_gen;
END_RCPP
}
// uuid_validate
std::vector<bool> uuid_validate(const std::vector<std::string>& x);
RcppExport SEXP _RcppUUID_uuid_validate(SEXP xSEXP) {
BEGIN_RCPP
Rcpp::RObject rcpp_result_gen;
Rcpp::traits::input_parameter< const std::vector<std::string>& >::type x(xSEXP);
rcpp_result_gen = Rcpp::wrap(uuid_validate(x));
return rcpp_result_gen;
END_RCPP
}
static const R_CallMethodDef CallEntries[] = {
{"_RcppUUID_uuid_generate_random", (DL_FUNC) &_RcppUUID_uuid_generate_random, 1},
{"_RcppUUID_uuid_generate_nil", (DL_FUNC) &_RcppUUID_uuid_generate_nil, 1},
{"_RcppUUID_uuid_generate_name", (DL_FUNC) &_RcppUUID_uuid_generate_name, 1},
{"_RcppUUID_uuid_validate", (DL_FUNC) &_RcppUUID_uuid_validate, 1},
{NULL, NULL, 0}
};
......
......@@ -4,32 +4,31 @@
#include <boost/uuid/uuid_io.hpp>
using namespace Rcpp;
using namespace boost::uuids;
//' @rdname uuid_generate
//' @rdname uuid
//' @export
// [[Rcpp::export(rng=false)]]
std::vector<std::string> uuid_generate_random(size_t n = 1) {
std::vector<std::string> res(n);
auto gen = random_generator();
boost::uuids::random_generator gen;
#pragma omp parallel for
for (size_t i = 0; i < n; ++i) {
uuid id = gen();
boost::uuids::uuid id = gen();
res[i] = to_string(id);
}
return res;
}
//' @rdname uuid_generate
//' @rdname uuid
//' @export
// [[Rcpp::export(rng=false)]]
std::vector<std::string> uuid_generate_nil(size_t n = 1) {
auto gen = nil_generator();
uuid id = gen();
boost::uuids::nil_generator gen;
boost::uuids::uuid id = gen();
std::string val = to_string(id);
std::vector<std::string> res(n);
#pragma omp parallel for
#pragma omp parallel for
for (size_t i = 0; i < n; ++i) {
res[i] = val;
}
......@@ -37,21 +36,40 @@ std::vector<std::string> uuid_generate_nil(size_t n = 1) {
}
//' @rdname uuid_generate
//' @rdname uuid
//' @export
// [[Rcpp::export(rng=false)]]
std::vector<std::string> uuid_generate_name(const std::vector<std::string>& x) {
size_t n = x.size();
std::vector<std::string> res(n);
auto ns = ns::x500dn();
auto gen = name_generator_sha1(ns);
#pragma omp parallel for
boost::uuids::name_generator_sha1 gen(boost::uuids::ns::x500dn());
auto nil_uuid = boost::uuids::nil_generator()();
#pragma omp parallel for
for (size_t i = 0; i < n; ++i) {
boost::uuids::uuid id = x[i].empty() ? nil_uuid : gen(x[i]);
res[i] = to_string(id);
}
return res;
}
//' @rdname uuid
//' @export
// [[Rcpp::export(rng=false)]]
std::vector<bool> uuid_validate(const std::vector<std::string>& x) {
size_t n = x.size();
std::vector<bool> res(n);
boost::uuids::string_generator gen;
for (size_t i = 0; i < n; ++i) {
if (x[i].empty()) {
res[i] = to_string(nil_generator()());
res[i] = false;
} else {
uuid id = gen(x[i]);
res[i] = to_string(id);
try {
boost::uuids::uuid id = gen(x[i]);
res[i] = id.is_nil() || id.version() != boost::uuids::uuid::version_unknown;
} catch(...) {
res[i] = false;
}
}
}
return res;
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment