From 03470841f744510f1299b829dc7cdbefdb295cd9 Mon Sep 17 00:00:00 2001 From: hrbrmstr Date: Thu, 4 Jul 2019 18:44:21 -0400 Subject: [PATCH] update library; switch to tinytest; add vignette --- .Rbuildignore | 1 + .gitignore | 1 + .travis.yml | 3 +- DESCRIPTION | 61 +-- NEWS.md | 9 + README.Rmd | 11 +- README.md | 84 ++-- appveyor.yml | 52 +++ inst/tinytest/test_ulid.R | 27 ++ src/ulid-main.cpp | 6 + src/ulid.h | 5 +- src/ulid_struct.h | 1005 ++++++++++++++++++++++--------------------- src/ulid_uint128.h | 617 +++++++++++++------------- tests/test-all.R | 2 - tests/testthat/test-ulid.R | 6 - tests/tinytest.R | 5 + vignettes/.gitignore | 2 + vignettes/intro-to-ulid.Rmd | 45 ++ 18 files changed, 1077 insertions(+), 865 deletions(-) create mode 100644 appveyor.yml create mode 100644 inst/tinytest/test_ulid.R delete mode 100644 tests/test-all.R delete mode 100644 tests/testthat/test-ulid.R create mode 100644 tests/tinytest.R create mode 100644 vignettes/.gitignore create mode 100644 vignettes/intro-to-ulid.Rmd diff --git a/.Rbuildignore b/.Rbuildignore index c027b43..43d710e 100644 --- a/.Rbuildignore +++ b/.Rbuildignore @@ -12,3 +12,4 @@ ^tmp$ ^notes$ ^\.gitlab-ci\.yml$ +^appveyor\.yml$ diff --git a/.gitignore b/.gitignore index cce1f17..96a4b63 100644 --- a/.gitignore +++ b/.gitignore @@ -6,3 +6,4 @@ src/*.o src/*.so src/*.dll +inst/doc diff --git a/.travis.yml b/.travis.yml index f93993f..b5fbd79 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,6 +1,5 @@ language: R -sudo: false cache: packages after_success: -- Rscript -e 'covr::codecov()' + - Rscript -e 'covr::codecov()' diff --git a/DESCRIPTION b/DESCRIPTION index ae37773..c1f90db 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,41 +1,42 @@ Package: ulid Type: Package Title: Generate Universally Unique Lexicographically Sortable Identifier -Version: 0.1.0 -Date: 2018-12-28 -Authors@R: c( - person("Bob", "Rudis", email = "bob@rud.is", role = c("aut", "cre"), - comment = c(ORCID = "0000-0001-5670-2640")), - person("suyash", role = c("aut"), - comment = "ULID C++ Port ") - ) +Version: 0.3.0 +Date: 2019-07-04 +Authors@R: c( person("Bob", "Rudis", email = "bob@rud.is", role = + c("aut", "cre"), comment = c(ORCID = "0000-0001-5670-2640")), + person("suyash", role = c("aut"), comment = "ULID C++ Port + ") ) Maintainer: Bob Rudis -Description: Universally unique identifiers ('UUIDs') can be suboptimal for many - uses-cases because they aren't the most character efficient way of encoding - 128 bits of randomness; v1/v2 versions are impractical in many environments, - as they require access to a unique, stable MAC address; v3/v5 versions require - a unique seed and produce randomly distributed IDs, which can cause fragmentation - in many data structures; v4 provides no other information than randomness which - can cause fragmentation in many data structures. 'ULIDs' () - have 128-bit compatibility with 'UUID', 1.21e+24 unique ULIDs per millisecond, - are lexicographically sortable, canonically encoded as a 26 character string, - as opposed to the 36 character 'UUID', use Crockford's 'base32' for better - efficiency and readability (5 bits per character), are case insensitive, - have no special characters (i.e. are 'URL' safe) and have a onotonic sort order - (correctly detects and handles the same millisecond). +Description: Universally unique identifiers ('UUIDs') can be suboptimal + for many uses-cases because they aren't the most character + efficient way of encoding 128 bits of randomness; v1/v2 versions + are impractical in many environments, as they require access to a + unique, stable MAC address; v3/v5 versions require a unique seed + and produce randomly distributed IDs, which can cause + fragmentation in many data structures; v4 provides no other + information than randomness which can cause fragmentation in many + data structures. 'ULIDs' () have + 128-bit compatibility with 'UUID', 1.21e+24 unique ULIDs per + millisecond, are lexicographically sortable, canonically encoded + as a 26 character string, as opposed to the 36 character 'UUID', + use Crockford's 'base32' for better efficiency and readability (5 + bits per character), are case insensitive, have no special + characters (i.e. are 'URL' safe) and have a onotonic sort order + (correctly detects and handles the same millisecond). URL: https://gitlab.com/hrbrmstr/ulid BugReports: https://gitlab.com/hrbrmstr/ulid/issues SystemRequirements: C++11 NeedsCompilation: yes Encoding: UTF-8 License: MIT + file LICENSE -Suggests: - testthat, - covr -Depends: - R (>= 3.2.0) -Imports: - Rcpp +Suggests: + covr, + tinytest, + knitr, + rmarkdown +Depends: R (>= 3.2.0) +Imports: Rcpp RoxygenNote: 6.1.1 -LinkingTo: - Rcpp +LinkingTo: Rcpp +VignetteBuilder: knitr diff --git a/NEWS.md b/NEWS.md index 9b4679b..bf584ee 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,2 +1,11 @@ +0.3.0 +* Updated libary +* Uses R C random bits vs `std::rand()` +* Vignette +* Converted to {tinytest} + +0.2.0 +* Polished version + 0.1.0 * Initial release diff --git a/README.Rmd b/README.Rmd index c6af2c9..7b82aff 100644 --- a/README.Rmd +++ b/README.Rmd @@ -2,6 +2,11 @@ output: rmarkdown::github_document --- +[![Travis-CI Build Status](https://travis-ci.org/hrbrmstr/ulid.svg?branch=master)](https://travis-ci.org/hrbrmstr/ulid) +[![AppVeyor build status](https://ci.appveyor.com/api/projects/status/github/hrbrmstr/ulid?branch=master&svg=true)](https://ci.appveyor.com/project/hrbrmstr/ulid) +[![Coverage Status](https://codecov.io/gh/hrbrmstr/ulid/branch/master/graph/badge.svg)](https://codecov.io/gh/hrbrmstr/ulid) +[![CRAN_Status_Badge](https://www.r-pkg.org/badges/version/ulid)](https://cran.r-project.org/package=ulid) + # ulid Universally Unique Lexicographically Sortable Identifier @@ -65,8 +70,8 @@ The following functions are implemented: ## Installation -```{r eval=FALSE} -devtools::install_github("hrbrmstr/ulid") +```{r nstall-ex, results='asis', echo = FALSE} +hrbrpkghelpr::install_block() ``` ```{r message=FALSE, warning=FALSE, error=FALSE, include=FALSE} @@ -113,4 +118,4 @@ unmarshal(ut) ```{r} cloc::cloc_pkg_md() -``` \ No newline at end of file +``` diff --git a/README.md b/README.md index 604f51a..93039c4 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,12 @@ +[![Travis-CI Build +Status](https://travis-ci.org/hrbrmstr/ulid.svg?branch=master)](https://travis-ci.org/hrbrmstr/ulid) +[![AppVeyor build +status](https://ci.appveyor.com/api/projects/status/github/hrbrmstr/ulid?branch=master&svg=true)](https://ci.appveyor.com/project/hrbrmstr/ulid) +[![Coverage +Status](https://codecov.io/gh/hrbrmstr/ulid/branch/master/graph/badge.svg)](https://codecov.io/gh/hrbrmstr/ulid) +[![CRAN\_Status\_Badge](https://www.r-pkg.org/badges/version/ulid)](https://cran.r-project.org/package=ulid) + # ulid Universally Unique Lexicographically Sortable Identifier @@ -73,6 +81,12 @@ The following functions are implemented: ## Installation ``` r +install.packages("ulid", repos = "https://cinc.rud.is") +# or +devtools::install_git("https://git.sr.ht/~hrbrmstr/ulid") +# or +devtools::install_gitlab("hrbrmstr/ulid") +# or devtools::install_github("hrbrmstr/ulid") ``` @@ -85,7 +99,7 @@ library(ulid) packageVersion("ulid") ``` - ## [1] '0.1.0' + ## [1] '0.3.0' ### One @@ -93,7 +107,7 @@ packageVersion("ulid") ulid::ULIDgenerate() ``` - ## [1] "0001E2ERKHVPKZJ6FA6ZWHH1KS" + ## [1] "0001EHX06QWTHZTAT6TE2GVAVT" ### Many @@ -101,11 +115,11 @@ ulid::ULIDgenerate() (u <- ulid::ULIDgenerate(20)) ``` - ## [1] "0001E2ERKHVX5QF5D59SX2E65T" "0001E2ERKHKD6MHKYB1G8JHN5X" "0001E2ERKHTK0XEHVV2G5877K9" "0001E2ERKHKFGG5NPN24PC1N0W" - ## [5] "0001E2ERKH3F48CAKJCVMSCBKS" "0001E2ERKHF3N0B94VK05GTXCW" "0001E2ERKH24GCJ2CT3Z5WM1FD" "0001E2ERKH381RJ232KK7SMWQW" - ## [9] "0001E2ERKH7NAZ1T4HR4ZRQRND" "0001E2ERKHSATC17G2QAPYXE0C" "0001E2ERKH76R83NFST3MZNW84" "0001E2ERKHFKS52SD8WJ8FHXMV" - ## [13] "0001E2ERKHQM6VBM5JB235JJ1W" "0001E2ERKHXG2KNYWHHFS8X69Z" "0001E2ERKHQW821KPRM4GQFANJ" "0001E2ERKHD5KWTM5S345A3RP4" - ## [17] "0001E2ERKH0D901W6KX66B1BHE" "0001E2ERKHKPHZBFSC16FC7FFC" "0001E2ERKHQQH7315GMY8HRYXV" "0001E2ERKH016YBAJAB7K9777T" + ## [1] "0001EHX06Q1C0H9NQPZQW7YN65" "0001EHX06QN1D7PYNDZ33B7QF1" "0001EHX06QZHV13RGNDWAJ7VX9" "0001EHX06Q2XC40QWY7AFR8DCZ" + ## [5] "0001EHX06QXWZRT9EJ1YM75214" "0001EHX06QYDSTG3KRWSKG01EE" "0001EHX06QNC8YWTX0H2M7HHYQ" "0001EHX06QFPBJWQ1PAQ1KXTJY" + ## [9] "0001EHX06Q6HW1WE5GP8Q9J6D6" "0001EHX06Q3QEY4KF2DX0FKTFB" "0001EHX06QS3FDSPSHW2W7AB7X" "0001EHX06QS2VENPTAADWYKAQW" + ## [13] "0001EHX06QQJ7XEK9ZDT5542SD" "0001EHX06QHWVRKRF2SC86KB3Z" "0001EHX06QKG0V1129FBA0A5XY" "0001EHX06QY66KTA09CB9KKQP8" + ## [17] "0001EHX06QZ9VMBDT8YZMXK1B5" "0001EHX06QJ60ZFVA45DFAGB5R" "0001EHX06QC0CXK917QFWXA71M" "0001EHX06QBW2TTWPDAFG23J7E" ### Unmarshal @@ -114,26 +128,26 @@ unmarshal(u) ``` ## ts rnd - ## 1 2018-12-29 07:02:57 VX5QF5D59SX2E65T - ## 2 2018-12-29 07:02:57 KD6MHKYB1G8JHN5X - ## 3 2018-12-29 07:02:57 TK0XEHVV2G5877K9 - ## 4 2018-12-29 07:02:57 KFGG5NPN24PC1N0W - ## 5 2018-12-29 07:02:57 3F48CAKJCVMSCBKS - ## 6 2018-12-29 07:02:57 F3N0B94VK05GTXCW - ## 7 2018-12-29 07:02:57 24GCJ2CT3Z5WM1FD - ## 8 2018-12-29 07:02:57 381RJ232KK7SMWQW - ## 9 2018-12-29 07:02:57 7NAZ1T4HR4ZRQRND - ## 10 2018-12-29 07:02:57 SATC17G2QAPYXE0C - ## 11 2018-12-29 07:02:57 76R83NFST3MZNW84 - ## 12 2018-12-29 07:02:57 FKS52SD8WJ8FHXMV - ## 13 2018-12-29 07:02:57 QM6VBM5JB235JJ1W - ## 14 2018-12-29 07:02:57 XG2KNYWHHFS8X69Z - ## 15 2018-12-29 07:02:57 QW821KPRM4GQFANJ - ## 16 2018-12-29 07:02:57 D5KWTM5S345A3RP4 - ## 17 2018-12-29 07:02:57 0D901W6KX66B1BHE - ## 18 2018-12-29 07:02:57 KPHZBFSC16FC7FFC - ## 19 2018-12-29 07:02:57 QQH7315GMY8HRYXV - ## 20 2018-12-29 07:02:57 016YBAJAB7K9777T + ## 1 2019-07-04 18:42:31 1C0H9NQPZQW7YN65 + ## 2 2019-07-04 18:42:31 N1D7PYNDZ33B7QF1 + ## 3 2019-07-04 18:42:31 ZHV13RGNDWAJ7VX9 + ## 4 2019-07-04 18:42:31 2XC40QWY7AFR8DCZ + ## 5 2019-07-04 18:42:31 XWZRT9EJ1YM75214 + ## 6 2019-07-04 18:42:31 YDSTG3KRWSKG01EE + ## 7 2019-07-04 18:42:31 NC8YWTX0H2M7HHYQ + ## 8 2019-07-04 18:42:31 FPBJWQ1PAQ1KXTJY + ## 9 2019-07-04 18:42:31 6HW1WE5GP8Q9J6D6 + ## 10 2019-07-04 18:42:31 3QEY4KF2DX0FKTFB + ## 11 2019-07-04 18:42:31 S3FDSPSHW2W7AB7X + ## 12 2019-07-04 18:42:31 S2VENPTAADWYKAQW + ## 13 2019-07-04 18:42:31 QJ7XEK9ZDT5542SD + ## 14 2019-07-04 18:42:31 HWVRKRF2SC86KB3Z + ## 15 2019-07-04 18:42:31 KG0V1129FBA0A5XY + ## 16 2019-07-04 18:42:31 Y66KTA09CB9KKQP8 + ## 17 2019-07-04 18:42:31 Z9VMBDT8YZMXK1B5 + ## 18 2019-07-04 18:42:31 J60ZFVA45DFAGB5R + ## 19 2019-07-04 18:42:31 C0CXK917QFWXA71M + ## 20 2019-07-04 18:42:31 BW2TTWPDAFG23J7E ### Use defined timestamps @@ -141,14 +155,14 @@ unmarshal(u) (ut <- ts_generate(as.POSIXct("2017-11-01 15:00:00", origin="1970-01-01"))) ``` - ## [1] "0001CZM6DGE66RJEY4N05F5R95" + ## [1] "0001CZM6DGVRVF68B8AP8VATS0" ``` r unmarshal(ut) ``` ## ts rnd - ## 1 2017-11-01 15:00:00 E66RJEY4N05F5R95 + ## 1 2017-11-01 15:00:00 VRVF68B8AP8VATS0 ## Package Code Metrics @@ -156,9 +170,9 @@ unmarshal(ut) cloc::cloc_pkg_md() ``` -| Lang | \# Files | (%) | LoC | (%) | Blank lines | (%) | \# Lines | (%) | -| :----------- | -------: | ---: | --: | ---: | ----------: | ---: | -------: | ---: | -| C/C++ Header | 3 | 0.27 | 755 | 0.87 | 231 | 0.78 | 264 | 0.57 | -| C++ | 2 | 0.18 | 81 | 0.09 | 22 | 0.07 | 37 | 0.08 | -| R | 5 | 0.45 | 17 | 0.02 | 7 | 0.02 | 95 | 0.20 | -| Rmd | 1 | 0.09 | 10 | 0.01 | 37 | 0.12 | 69 | 0.15 | +| Lang | \# Files | (%) | LoC | (%) | Blank lines | (%) | \# Lines | (%) | +| :----------- | -------: | --: | --: | ---: | ----------: | ---: | -------: | ---: | +| C/C++ Header | 3 | 0.3 | 763 | 0.87 | 238 | 0.78 | 302 | 0.60 | +| C++ | 2 | 0.2 | 87 | 0.10 | 22 | 0.07 | 37 | 0.07 | +| R | 4 | 0.4 | 15 | 0.02 | 7 | 0.02 | 94 | 0.19 | +| Rmd | 1 | 0.1 | 10 | 0.01 | 38 | 0.12 | 73 | 0.14 | diff --git a/appveyor.yml b/appveyor.yml new file mode 100644 index 0000000..3a75e16 --- /dev/null +++ b/appveyor.yml @@ -0,0 +1,52 @@ +# DO NOT CHANGE the "init" and "install" sections below + +# Download script file from GitHub +init: + ps: | + $ErrorActionPreference = "Stop" + Invoke-WebRequest http://raw.github.com/krlmlr/r-appveyor/master/scripts/appveyor-tool.ps1 -OutFile "..\appveyor-tool.ps1" + Import-Module '..\appveyor-tool.ps1' + +install: + ps: Bootstrap + +cache: + - C:\RLibrary + +environment: + NOT_CRAN: true + # env vars that may need to be set, at least temporarily, from time to time + # see https://github.com/krlmlr/r-appveyor#readme for details + # USE_RTOOLS: true + # R_REMOTES_STANDALONE: true + +# Adapt as necessary starting from here + +build_script: + - travis-tool.sh install_deps + +test_script: + - travis-tool.sh run_tests + +on_failure: + - 7z a failure.zip *.Rcheck\* + - appveyor PushArtifact failure.zip + +artifacts: + - path: '*.Rcheck\**\*.log' + name: Logs + + - path: '*.Rcheck\**\*.out' + name: Logs + + - path: '*.Rcheck\**\*.fail' + name: Logs + + - path: '*.Rcheck\**\*.Rout' + name: Logs + + - path: '\*_*.tar.gz' + name: Bits + + - path: '\*_*.zip' + name: Bits diff --git a/inst/tinytest/test_ulid.R b/inst/tinytest/test_ulid.R new file mode 100644 index 0000000..02400ea --- /dev/null +++ b/inst/tinytest/test_ulid.R @@ -0,0 +1,27 @@ +library(ulid) + +x <- ULIDgenerate() +expect_true(is.character(x)) +expect_true(nchar(x) == 26) + +x <- ULIDgenerate(20) +expect_true(is.character(x)) +expect_true(length(x) == 20) +expect_true(sum(nchar(x)) == 520) +expect_true(all(rle(x)[["values"]] == x)) + +x <- unmarshal(x) +expect_true(is.data.frame(x)) +expect_true(nrow(x) == 20) +expect_true(inherits(x[["ts"]], "POSIXct")) +expect_true(is.character(x[["rnd"]])) +expect_true(sum(nchar(x[["rnd"]])) == 320) +expect_true(all(rle(x[["rnd"]])[["values"]] == x[["rnd"]])) + +x <- ts_generate(as.POSIXct("2017-11-01 15:00:00", origin="1970-01-01")) +y <- unmarshal(x) + +expect_true(is.data.frame(y)) +expect_true(y[["ts"]][[1]] == "2017-11-01 15:00:00") +expect_true(is.character(y[["rnd"]][[1]])) +expect_true(nchar(y[["rnd"]][[1]]) == 16) diff --git a/src/ulid-main.cpp b/src/ulid-main.cpp index 57e5b4d..8761096 100644 --- a/src/ulid-main.cpp +++ b/src/ulid-main.cpp @@ -28,6 +28,12 @@ CharacterVector ts_generate(Rcpp::DatetimeVector tsv) { return(c); } +inline long intrand() { + GetRNGstate(); + long ret = (long)(unif_rand()*RAND_MAX); + PutRNGstate(); + return(ret); +} //' Generate ULID //' diff --git a/src/ulid.h b/src/ulid.h index d07be99..30276a9 100644 --- a/src/ulid.h +++ b/src/ulid.h @@ -1,4 +1,5 @@ -#pragma once +#ifndef ULID_HH +#define ULID_HH // http://stackoverflow.com/a/23981011 #ifdef __SIZEOF_INT128__ @@ -10,3 +11,5 @@ #else #include "ulid_struct.h" #endif // ULIDUINT128 + +#endif // ULID_HH \ No newline at end of file diff --git a/src/ulid_struct.h b/src/ulid_struct.h index 2f53a2d..1db19bb 100644 --- a/src/ulid_struct.h +++ b/src/ulid_struct.h @@ -1,4 +1,5 @@ -#pragma once +#ifndef ULID_STRUCT_HH +#define ULID_STRUCT_HH #include #include @@ -7,288 +8,290 @@ #include #include +extern long intrand(); + namespace ulid { /** * ULID is a 16 byte Universally Unique Lexicographically Sortable Identifier * */ struct ULID { - uint8_t data[16]; - - ULID() { - // for (int i = 0 ; i < 16 ; i++) { - // data[i] = 0; - // } - - // unrolled loop - data[0] = 0; - data[1] = 0; - data[2] = 0; - data[3] = 0; - data[4] = 0; - data[5] = 0; - data[6] = 0; - data[7] = 0; - data[8] = 0; - data[9] = 0; - data[10] = 0; - data[11] = 0; - data[12] = 0; - data[13] = 0; - data[14] = 0; - data[15] = 0; - } - - ULID(uint64_t val) { - // for (int i = 0 ; i < 16 ; i++) { - // data[15 - i] = static_cast(val); - // val >>= 8; - // } - - // unrolled loop - data[15] = static_cast(val); - - val >>= 8; - data[14] = static_cast(val); - - val >>= 8; - data[13] = static_cast(val); - - val >>= 8; - data[12] = static_cast(val); - - val >>= 8; - data[11] = static_cast(val); - - val >>= 8; - data[10] = static_cast(val); - - val >>= 8; - data[9] = static_cast(val); - - val >>= 8; - data[8] = static_cast(val); - - data[7] = 0; - data[6] = 0; - data[5] = 0; - data[4] = 0; - data[3] = 0; - data[2] = 0; - data[1] = 0; - data[0] = 0; - } - - ULID(const ULID& other) { - // for (int i = 0 ; i < 16 ; i++) { - // data[i] = other.data[i]; - // } - - // unrolled loop - data[0] = other.data[0]; - data[1] = other.data[1]; - data[2] = other.data[2]; - data[3] = other.data[3]; - data[4] = other.data[4]; - data[5] = other.data[5]; - data[6] = other.data[6]; - data[7] = other.data[7]; - data[8] = other.data[8]; - data[9] = other.data[9]; - data[10] = other.data[10]; - data[11] = other.data[11]; - data[12] = other.data[12]; - data[13] = other.data[13]; - data[14] = other.data[14]; - data[15] = other.data[15]; - } - - ULID& operator=(const ULID& other) { - // for (int i = 0 ; i < 16 ; i++) { - // data[i] = other.data[i]; - // } - - // unrolled loop - data[0] = other.data[0]; - data[1] = other.data[1]; - data[2] = other.data[2]; - data[3] = other.data[3]; - data[4] = other.data[4]; - data[5] = other.data[5]; - data[6] = other.data[6]; - data[7] = other.data[7]; - data[8] = other.data[8]; - data[9] = other.data[9]; - data[10] = other.data[10]; - data[11] = other.data[11]; - data[12] = other.data[12]; - data[13] = other.data[13]; - data[14] = other.data[14]; - data[15] = other.data[15]; - - return *this; - } - - ULID(ULID&& other) { - // for (int i = 0 ; i < 16 ; i++) { - // data[i] = other.data[i]; - // other.data[i] = 0; - // } - - // unrolled loop - data[0] = other.data[0]; - other.data[0] = 0; - - data[1] = other.data[1]; - other.data[1] = 0; - - data[2] = other.data[2]; - other.data[2] = 0; + uint8_t data[16]; + + ULID() { + // for (int i = 0 ; i < 16 ; i++) { + // data[i] = 0; + // } + + // unrolled loop + data[0] = 0; + data[1] = 0; + data[2] = 0; + data[3] = 0; + data[4] = 0; + data[5] = 0; + data[6] = 0; + data[7] = 0; + data[8] = 0; + data[9] = 0; + data[10] = 0; + data[11] = 0; + data[12] = 0; + data[13] = 0; + data[14] = 0; + data[15] = 0; + } + + ULID(uint64_t val) { + // for (int i = 0 ; i < 16 ; i++) { + // data[15 - i] = static_cast(val); + // val >>= 8; + // } + + // unrolled loop + data[15] = static_cast(val); + + val >>= 8; + data[14] = static_cast(val); + + val >>= 8; + data[13] = static_cast(val); + + val >>= 8; + data[12] = static_cast(val); + + val >>= 8; + data[11] = static_cast(val); + + val >>= 8; + data[10] = static_cast(val); + + val >>= 8; + data[9] = static_cast(val); + + val >>= 8; + data[8] = static_cast(val); + + data[7] = 0; + data[6] = 0; + data[5] = 0; + data[4] = 0; + data[3] = 0; + data[2] = 0; + data[1] = 0; + data[0] = 0; + } + + ULID(const ULID& other) { + // for (int i = 0 ; i < 16 ; i++) { + // data[i] = other.data[i]; + // } + + // unrolled loop + data[0] = other.data[0]; + data[1] = other.data[1]; + data[2] = other.data[2]; + data[3] = other.data[3]; + data[4] = other.data[4]; + data[5] = other.data[5]; + data[6] = other.data[6]; + data[7] = other.data[7]; + data[8] = other.data[8]; + data[9] = other.data[9]; + data[10] = other.data[10]; + data[11] = other.data[11]; + data[12] = other.data[12]; + data[13] = other.data[13]; + data[14] = other.data[14]; + data[15] = other.data[15]; + } + + ULID& operator=(const ULID& other) { + // for (int i = 0 ; i < 16 ; i++) { + // data[i] = other.data[i]; + // } + + // unrolled loop + data[0] = other.data[0]; + data[1] = other.data[1]; + data[2] = other.data[2]; + data[3] = other.data[3]; + data[4] = other.data[4]; + data[5] = other.data[5]; + data[6] = other.data[6]; + data[7] = other.data[7]; + data[8] = other.data[8]; + data[9] = other.data[9]; + data[10] = other.data[10]; + data[11] = other.data[11]; + data[12] = other.data[12]; + data[13] = other.data[13]; + data[14] = other.data[14]; + data[15] = other.data[15]; + + return *this; + } + + ULID(ULID&& other) { + // for (int i = 0 ; i < 16 ; i++) { + // data[i] = other.data[i]; + // other.data[i] = 0; + // } + + // unrolled loop + data[0] = other.data[0]; + other.data[0] = 0; + + data[1] = other.data[1]; + other.data[1] = 0; + + data[2] = other.data[2]; + other.data[2] = 0; - data[3] = other.data[3]; - other.data[3] = 0; + data[3] = other.data[3]; + other.data[3] = 0; - data[4] = other.data[4]; - other.data[4] = 0; - - data[5] = other.data[5]; - other.data[5] = 0; - - data[6] = other.data[6]; - other.data[6] = 0; - - data[7] = other.data[7]; - other.data[7] = 0; - - data[8] = other.data[8]; - other.data[8] = 0; - - data[9] = other.data[9]; - other.data[9] = 0; - - data[10] = other.data[10]; - other.data[10] = 0; - - data[11] = other.data[11]; - other.data[11] = 0; - - data[12] = other.data[12]; - other.data[12] = 0; - - data[13] = other.data[13]; - other.data[13] = 0; - - data[14] = other.data[14]; - other.data[14] = 0; - - data[15] = other.data[15]; - other.data[15] = 0; - } - - ULID& operator=(ULID&& other) { - // for (int i = 0 ; i < 16 ; i++) { - // data[i] = other.data[i]; - // other.data[i] = 0; - // } + data[4] = other.data[4]; + other.data[4] = 0; + + data[5] = other.data[5]; + other.data[5] = 0; + + data[6] = other.data[6]; + other.data[6] = 0; + + data[7] = other.data[7]; + other.data[7] = 0; + + data[8] = other.data[8]; + other.data[8] = 0; + + data[9] = other.data[9]; + other.data[9] = 0; + + data[10] = other.data[10]; + other.data[10] = 0; + + data[11] = other.data[11]; + other.data[11] = 0; + + data[12] = other.data[12]; + other.data[12] = 0; + + data[13] = other.data[13]; + other.data[13] = 0; + + data[14] = other.data[14]; + other.data[14] = 0; + + data[15] = other.data[15]; + other.data[15] = 0; + } + + ULID& operator=(ULID&& other) { + // for (int i = 0 ; i < 16 ; i++) { + // data[i] = other.data[i]; + // other.data[i] = 0; + // } - // unrolled loop - data[0] = other.data[0]; - other.data[0] = 0; + // unrolled loop + data[0] = other.data[0]; + other.data[0] = 0; - data[1] = other.data[1]; - other.data[1] = 0; + data[1] = other.data[1]; + other.data[1] = 0; - data[2] = other.data[2]; - other.data[2] = 0; + data[2] = other.data[2]; + other.data[2] = 0; - data[3] = other.data[3]; - other.data[3] = 0; + data[3] = other.data[3]; + other.data[3] = 0; - data[4] = other.data[4]; - other.data[4] = 0; + data[4] = other.data[4]; + other.data[4] = 0; - data[5] = other.data[5]; - other.data[5] = 0; + data[5] = other.data[5]; + other.data[5] = 0; - data[6] = other.data[6]; - other.data[6] = 0; + data[6] = other.data[6]; + other.data[6] = 0; - data[7] = other.data[7]; - other.data[7] = 0; + data[7] = other.data[7]; + other.data[7] = 0; - data[8] = other.data[8]; - other.data[8] = 0; + data[8] = other.data[8]; + other.data[8] = 0; - data[9] = other.data[9]; - other.data[9] = 0; + data[9] = other.data[9]; + other.data[9] = 0; - data[10] = other.data[10]; - other.data[10] = 0; + data[10] = other.data[10]; + other.data[10] = 0; - data[11] = other.data[11]; - other.data[11] = 0; + data[11] = other.data[11]; + other.data[11] = 0; - data[12] = other.data[12]; - other.data[12] = 0; + data[12] = other.data[12]; + other.data[12] = 0; - data[13] = other.data[13]; - other.data[13] = 0; + data[13] = other.data[13]; + other.data[13] = 0; - data[14] = other.data[14]; - other.data[14] = 0; + data[14] = other.data[14]; + other.data[14] = 0; - data[15] = other.data[15]; - other.data[15] = 0; + data[15] = other.data[15]; + other.data[15] = 0; - return *this; - } + return *this; + } }; /** * EncodeTime will encode the first 6 bytes of a uint8_t array to the passed * timestamp * */ -void EncodeTime(time_t timestamp, ULID& ulid) { - ulid.data[0] = static_cast(timestamp >> 40); - ulid.data[1] = static_cast(timestamp >> 32); - ulid.data[2] = static_cast(timestamp >> 24); - ulid.data[3] = static_cast(timestamp >> 16); - ulid.data[4] = static_cast(timestamp >> 8); - ulid.data[5] = static_cast(timestamp); +inline void EncodeTime(time_t timestamp, ULID& ulid) { + ulid.data[0] = static_cast(timestamp >> 40); + ulid.data[1] = static_cast(timestamp >> 32); + ulid.data[2] = static_cast(timestamp >> 24); + ulid.data[3] = static_cast(timestamp >> 16); + ulid.data[4] = static_cast(timestamp >> 8); + ulid.data[5] = static_cast(timestamp); } /** * EncodeTimeNow will encode a ULID using the time obtained using std::time(nullptr) * */ -void EncodeTimeNow(ULID& ulid) { - EncodeTime(std::time(nullptr), ulid); +inline void EncodeTimeNow(ULID& ulid) { + EncodeTime(std::time(nullptr), ulid); } /** * EncodeTimeSystemClockNow will encode a ULID using the time obtained using * std::chrono::system_clock::now() by taking the timestamp in milliseconds. * */ -void EncodeTimeSystemClockNow(ULID& ulid) { - auto now = std::chrono::system_clock::now(); - auto ms = std::chrono::duration_cast(now.time_since_epoch()); - EncodeTime(ms.count(), ulid); +inline void EncodeTimeSystemClockNow(ULID& ulid) { + auto now = std::chrono::system_clock::now(); + auto ms = std::chrono::duration_cast(now.time_since_epoch()); + EncodeTime(ms.count(), ulid); } /** * EncodeEntropy will encode the last 10 bytes of the passed uint8_t array with * the values generated using the passed random number generator. * */ -void EncodeEntropy(const std::function& rng, ULID& ulid) { - ulid.data[6] = rng(); - ulid.data[7] = rng(); - ulid.data[8] = rng(); - ulid.data[9] = rng(); - ulid.data[10] = rng(); - ulid.data[11] = rng(); - ulid.data[12] = rng(); - ulid.data[13] = rng(); - ulid.data[14] = rng(); - ulid.data[15] = rng(); +inline void EncodeEntropy(const std::function& rng, ULID& ulid) { + ulid.data[6] = rng(); + ulid.data[7] = rng(); + ulid.data[8] = rng(); + ulid.data[9] = rng(); + ulid.data[10] = rng(); + ulid.data[11] = rng(); + ulid.data[12] = rng(); + ulid.data[13] = rng(); + ulid.data[14] = rng(); + ulid.data[15] = rng(); } /** @@ -297,76 +300,86 @@ void EncodeEntropy(const std::function& rng, ULID& ulid) { * std::rand returns values in [0, RAND_MAX] * */ void EncodeEntropyRand(ULID& ulid) { - ulid.data[6] = (std::rand() * 255ull) / RAND_MAX; - ulid.data[7] = (std::rand() * 255ull) / RAND_MAX; - ulid.data[8] = (std::rand() * 255ull) / RAND_MAX; - ulid.data[9] = (std::rand() * 255ull) / RAND_MAX; - ulid.data[10] = (std::rand() * 255ull) / RAND_MAX; - ulid.data[11] = (std::rand() * 255ull) / RAND_MAX; - ulid.data[12] = (std::rand() * 255ull) / RAND_MAX; - ulid.data[13] = (std::rand() * 255ull) / RAND_MAX; - ulid.data[14] = (std::rand() * 255ull) / RAND_MAX; - ulid.data[15] = (std::rand() * 255ull) / RAND_MAX; + ulid.data[6] = (intrand() * 255ull) / RAND_MAX; + ulid.data[7] = (intrand() * 255ull) / RAND_MAX; + ulid.data[8] = (intrand() * 255ull) / RAND_MAX; + ulid.data[9] = (intrand() * 255ull) / RAND_MAX; + ulid.data[10] = (intrand() * 255ull) / RAND_MAX; + ulid.data[11] = (intrand() * 255ull) / RAND_MAX; + ulid.data[12] = (intrand() * 255ull) / RAND_MAX; + ulid.data[13] = (intrand() * 255ull) / RAND_MAX; + ulid.data[14] = (intrand() * 255ull) / RAND_MAX; + ulid.data[15] = (intrand() * 255ull) / RAND_MAX; + // ulid.data[6] = (std::rand() * 255ull) / RAND_MAX; + // ulid.data[7] = (std::rand() * 255ull) / RAND_MAX; + // ulid.data[8] = (std::rand() * 255ull) / RAND_MAX; + // ulid.data[9] = (std::rand() * 255ull) / RAND_MAX; + // ulid.data[10] = (std::rand() * 255ull) / RAND_MAX; + // ulid.data[11] = (std::rand() * 255ull) / RAND_MAX; + // ulid.data[12] = (std::rand() * 255ull) / RAND_MAX; + // ulid.data[13] = (std::rand() * 255ull) / RAND_MAX; + // ulid.data[14] = (std::rand() * 255ull) / RAND_MAX; + // ulid.data[15] = (std::rand() * 255ull) / RAND_MAX; } -std::uniform_int_distribution Distribution_0_255(0, 255); +static std::uniform_int_distribution Distribution_0_255(0, 255); /** * EncodeEntropyMt19937 will encode a ulid using std::mt19937 * * It also creates a std::uniform_int_distribution to generate values in [0, 255] * */ -void EncodeEntropyMt19937(std::mt19937& generator, ULID& ulid) { - ulid.data[6] = Distribution_0_255(generator); - ulid.data[7] = Distribution_0_255(generator); - ulid.data[8] = Distribution_0_255(generator); - ulid.data[9] = Distribution_0_255(generator); - ulid.data[10] = Distribution_0_255(generator); - ulid.data[11] = Distribution_0_255(generator); - ulid.data[12] = Distribution_0_255(generator); - ulid.data[13] = Distribution_0_255(generator); - ulid.data[14] = Distribution_0_255(generator); - ulid.data[15] = Distribution_0_255(generator); +inline void EncodeEntropyMt19937(std::mt19937& generator, ULID& ulid) { + ulid.data[6] = Distribution_0_255(generator); + ulid.data[7] = Distribution_0_255(generator); + ulid.data[8] = Distribution_0_255(generator); + ulid.data[9] = Distribution_0_255(generator); + ulid.data[10] = Distribution_0_255(generator); + ulid.data[11] = Distribution_0_255(generator); + ulid.data[12] = Distribution_0_255(generator); + ulid.data[13] = Distribution_0_255(generator); + ulid.data[14] = Distribution_0_255(generator); + ulid.data[15] = Distribution_0_255(generator); } /** * Encode will create an encoded ULID with a timestamp and a generator. * */ -void Encode(time_t timestamp, const std::function& rng, ULID& ulid) { - EncodeTime(timestamp, ulid); - EncodeEntropy(rng, ulid); +inline void Encode(time_t timestamp, const std::function& rng, ULID& ulid) { + EncodeTime(timestamp, ulid); + EncodeEntropy(rng, ulid); } /** * EncodeNowRand = EncodeTimeNow + EncodeEntropyRand. * */ -void EncodeNowRand(ULID& ulid) { - EncodeTimeNow(ulid); - EncodeEntropyRand(ulid); +inline void EncodeNowRand(ULID& ulid) { + EncodeTimeNow(ulid); + EncodeEntropyRand(ulid); } /** * Create will create a ULID with a timestamp and a generator. * */ -ULID Create(time_t timestamp, const std::function& rng) { - ULID ulid; - Encode(timestamp, rng, ulid); - return ulid; +inline ULID Create(time_t timestamp, const std::function& rng) { + ULID ulid; + Encode(timestamp, rng, ulid); + return ulid; } /** * CreateNowRand:EncodeNowRand = Create:Encode. * */ -ULID CreateNowRand() { - ULID ulid; - EncodeNowRand(ulid); - return ulid; +inline ULID CreateNowRand() { + ULID ulid; + EncodeNowRand(ulid); + return ulid; } /** * Crockford's Base32 * */ -const char Encoding[33] = "0123456789ABCDEFGHJKMNPQRSTVWXYZ"; +static const char Encoding[33] = "0123456789ABCDEFGHJKMNPQRSTVWXYZ"; /** * MarshalTo will marshal a ULID to the passed character array. @@ -389,80 +402,80 @@ const char Encoding[33] = "0123456789ABCDEFGHJKMNPQRSTVWXYZ"; * entropy: * follows similarly, except now all components are set to 5 bits. * */ -void MarshalTo(const ULID& ulid, char dst[26]) { - // 10 byte timestamp - dst[0] = Encoding[(ulid.data[0] & 224) >> 5]; - dst[1] = Encoding[ulid.data[0] & 31]; - dst[2] = Encoding[(ulid.data[1] & 248) >> 3]; - dst[3] = Encoding[((ulid.data[1] & 7) << 2) | ((ulid.data[2] & 192) >> 6)]; - dst[4] = Encoding[(ulid.data[2] & 62) >> 1]; - dst[5] = Encoding[((ulid.data[2] & 1) << 4) | ((ulid.data[3] & 240) >> 4)]; - dst[6] = Encoding[((ulid.data[3] & 15) << 1) | ((ulid.data[4] & 128) >> 7)]; - dst[7] = Encoding[(ulid.data[4] & 124) >> 2]; - dst[8] = Encoding[((ulid.data[4] & 3) << 3) | ((ulid.data[5] & 224) >> 5)]; - dst[9] = Encoding[ulid.data[5] & 31]; - - // 16 bytes of entropy - dst[10] = Encoding[(ulid.data[6] & 248) >> 3]; - dst[11] = Encoding[((ulid.data[6] & 7) << 2) | ((ulid.data[7] & 192) >> 6)]; - dst[12] = Encoding[(ulid.data[7] & 62) >> 1]; - dst[13] = Encoding[((ulid.data[7] & 1) << 4) | ((ulid.data[8] & 240) >> 4)]; - dst[14] = Encoding[((ulid.data[8] & 15) << 1) | ((ulid.data[9] & 128) >> 7)]; - dst[15] = Encoding[(ulid.data[9] & 124) >> 2]; - dst[16] = Encoding[((ulid.data[9] & 3) << 3) | ((ulid.data[10] & 224) >> 5)]; - dst[17] = Encoding[ulid.data[10] & 31]; - dst[18] = Encoding[(ulid.data[11] & 248) >> 3]; - dst[19] = Encoding[((ulid.data[11] & 7) << 2) | ((ulid.data[12] & 192) >> 6)]; - dst[20] = Encoding[(ulid.data[12] & 62) >> 1]; - dst[21] = Encoding[((ulid.data[12] & 1) << 4) | ((ulid.data[13] & 240) >> 4)]; - dst[22] = Encoding[((ulid.data[13] & 15) << 1) | ((ulid.data[14] & 128) >> 7)]; - dst[23] = Encoding[(ulid.data[14] & 124) >> 2]; - dst[24] = Encoding[((ulid.data[14] & 3) << 3) | ((ulid.data[15] & 224) >> 5)]; - dst[25] = Encoding[ulid.data[15] & 31]; +inline void MarshalTo(const ULID& ulid, char dst[26]) { + // 10 byte timestamp + dst[0] = Encoding[(ulid.data[0] & 224) >> 5]; + dst[1] = Encoding[ulid.data[0] & 31]; + dst[2] = Encoding[(ulid.data[1] & 248) >> 3]; + dst[3] = Encoding[((ulid.data[1] & 7) << 2) | ((ulid.data[2] & 192) >> 6)]; + dst[4] = Encoding[(ulid.data[2] & 62) >> 1]; + dst[5] = Encoding[((ulid.data[2] & 1) << 4) | ((ulid.data[3] & 240) >> 4)]; + dst[6] = Encoding[((ulid.data[3] & 15) << 1) | ((ulid.data[4] & 128) >> 7)]; + dst[7] = Encoding[(ulid.data[4] & 124) >> 2]; + dst[8] = Encoding[((ulid.data[4] & 3) << 3) | ((ulid.data[5] & 224) >> 5)]; + dst[9] = Encoding[ulid.data[5] & 31]; + + // 16 bytes of entropy + dst[10] = Encoding[(ulid.data[6] & 248) >> 3]; + dst[11] = Encoding[((ulid.data[6] & 7) << 2) | ((ulid.data[7] & 192) >> 6)]; + dst[12] = Encoding[(ulid.data[7] & 62) >> 1]; + dst[13] = Encoding[((ulid.data[7] & 1) << 4) | ((ulid.data[8] & 240) >> 4)]; + dst[14] = Encoding[((ulid.data[8] & 15) << 1) | ((ulid.data[9] & 128) >> 7)]; + dst[15] = Encoding[(ulid.data[9] & 124) >> 2]; + dst[16] = Encoding[((ulid.data[9] & 3) << 3) | ((ulid.data[10] & 224) >> 5)]; + dst[17] = Encoding[ulid.data[10] & 31]; + dst[18] = Encoding[(ulid.data[11] & 248) >> 3]; + dst[19] = Encoding[((ulid.data[11] & 7) << 2) | ((ulid.data[12] & 192) >> 6)]; + dst[20] = Encoding[(ulid.data[12] & 62) >> 1]; + dst[21] = Encoding[((ulid.data[12] & 1) << 4) | ((ulid.data[13] & 240) >> 4)]; + dst[22] = Encoding[((ulid.data[13] & 15) << 1) | ((ulid.data[14] & 128) >> 7)]; + dst[23] = Encoding[(ulid.data[14] & 124) >> 2]; + dst[24] = Encoding[((ulid.data[14] & 3) << 3) | ((ulid.data[15] & 224) >> 5)]; + dst[25] = Encoding[ulid.data[15] & 31]; } /** * Marshal will marshal a ULID to a std::string. * */ -std::string Marshal(const ULID& ulid) { - char data[27]; - data[26] = '\0'; - MarshalTo(ulid, data); - return std::string(data); +inline std::string Marshal(const ULID& ulid) { + char data[27]; + data[26] = '\0'; + MarshalTo(ulid, data); + return std::string(data); } /** * MarshalBinaryTo will Marshal a ULID to the passed byte array * */ -void MarshalBinaryTo(const ULID& ulid, uint8_t dst[16]) { - // timestamp - dst[0] = ulid.data[0]; - dst[1] = ulid.data[1]; - dst[2] = ulid.data[2]; - dst[3] = ulid.data[3]; - dst[4] = ulid.data[4]; - dst[5] = ulid.data[5]; - - // entropy - dst[6] = ulid.data[6]; - dst[7] = ulid.data[7]; - dst[8] = ulid.data[8]; - dst[9] = ulid.data[9]; - dst[10] = ulid.data[10]; - dst[11] = ulid.data[11]; - dst[12] = ulid.data[12]; - dst[13] = ulid.data[13]; - dst[14] = ulid.data[14]; - dst[15] = ulid.data[15]; +inline void MarshalBinaryTo(const ULID& ulid, uint8_t dst[16]) { + // timestamp + dst[0] = ulid.data[0]; + dst[1] = ulid.data[1]; + dst[2] = ulid.data[2]; + dst[3] = ulid.data[3]; + dst[4] = ulid.data[4]; + dst[5] = ulid.data[5]; + + // entropy + dst[6] = ulid.data[6]; + dst[7] = ulid.data[7]; + dst[8] = ulid.data[8]; + dst[9] = ulid.data[9]; + dst[10] = ulid.data[10]; + dst[11] = ulid.data[11]; + dst[12] = ulid.data[12]; + dst[13] = ulid.data[13]; + dst[14] = ulid.data[14]; + dst[15] = ulid.data[15]; } /** * MarshalBinary will Marshal a ULID to a byte vector. * */ -std::vector MarshalBinary(const ULID& ulid) { - std::vector dst(16); - MarshalBinaryTo(ulid, dst.data()); - return dst; +inline std::vector MarshalBinary(const ULID& ulid) { + std::vector dst(16); + MarshalBinaryTo(ulid, dst.data()); + return dst; } /** @@ -471,120 +484,120 @@ std::vector MarshalBinary(const ULID& ulid) { * 48-57 are digits. * 65-90 are capital alphabets. * */ -const uint8_t dec[256] = { - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - /* 0 1 2 3 4 5 6 7 */ - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - /* 8 9 */ - 0x08, 0x09, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - - /* 10(A) 11(B) 12(C) 13(D) 14(E) 15(F) 16(G) */ - 0xFF, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, - /*17(H) 18(J) 19(K) 20(M) 21(N) */ - 0x11, 0xFF, 0x12, 0x13, 0xFF, 0x14, 0x15, 0xFF, - /*22(P)23(Q)24(R) 25(S) 26(T) 27(V) 28(W) */ - 0x16, 0x17, 0x18, 0x19, 0x1A, 0xFF, 0x1B, 0x1C, - /*29(X)30(Y)31(Z) */ - 0x1D, 0x1E, 0x1F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF +static const uint8_t dec[256] = { + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + /* 0 1 2 3 4 5 6 7 */ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + /* 8 9 */ + 0x08, 0x09, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + + /* 10(A) 11(B) 12(C) 13(D) 14(E) 15(F) 16(G) */ + 0xFF, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, + /*17(H) 18(J) 19(K) 20(M) 21(N) */ + 0x11, 0xFF, 0x12, 0x13, 0xFF, 0x14, 0x15, 0xFF, + /*22(P)23(Q)24(R) 25(S) 26(T) 27(V) 28(W) */ + 0x16, 0x17, 0x18, 0x19, 0x1A, 0xFF, 0x1B, 0x1C, + /*29(X)30(Y)31(Z) */ + 0x1D, 0x1E, 0x1F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; /** * UnmarshalFrom will unmarshal a ULID from the passed character array. * */ -void UnmarshalFrom(const char str[26], ULID& ulid) { - // timestamp - ulid.data[0] = (dec[int(str[0])] << 5) | dec[int(str[1])]; - ulid.data[1] = (dec[int(str[2])] << 3) | (dec[int(str[3])] >> 2); - ulid.data[2] = (dec[int(str[3])] << 6) | (dec[int(str[4])] << 1) | (dec[int(str[5])] >> 4); - ulid.data[3] = (dec[int(str[5])] << 4) | (dec[int(str[6])] >> 1); - ulid.data[4] = (dec[int(str[6])] << 7) | (dec[int(str[7])] << 2) | (dec[int(str[8])] >> 3); - ulid.data[5] = (dec[int(str[8])] << 5) | dec[int(str[9])]; - - // entropy - ulid.data[6] = (dec[int(str[10])] << 3) | (dec[int(str[11])] >> 2); - ulid.data[7] = (dec[int(str[11])] << 6) | (dec[int(str[12])] << 1) | (dec[int(str[13])] >> 4); - ulid.data[8] = (dec[int(str[13])] << 4) | (dec[int(str[14])] >> 1); - ulid.data[9] = (dec[int(str[14])] << 7) | (dec[int(str[15])] << 2) | (dec[int(str[16])] >> 3); - ulid.data[10] = (dec[int(str[16])] << 5) | dec[int(str[17])]; - ulid.data[11] = (dec[int(str[18])] << 3) | (dec[int(str[19])] >> 2); - ulid.data[12] = (dec[int(str[19])] << 6) | (dec[int(str[20])] << 1) | (dec[int(str[21])] >> 4); - ulid.data[13] = (dec[int(str[21])] << 4) | (dec[int(str[22])] >> 1); - ulid.data[14] = (dec[int(str[22])] << 7) | (dec[int(str[23])] << 2) | (dec[int(str[24])] >> 3); - ulid.data[15] = (dec[int(str[24])] << 5) | dec[int(str[25])]; +inline void UnmarshalFrom(const char str[26], ULID& ulid) { + // timestamp + ulid.data[0] = (dec[int(str[0])] << 5) | dec[int(str[1])]; + ulid.data[1] = (dec[int(str[2])] << 3) | (dec[int(str[3])] >> 2); + ulid.data[2] = (dec[int(str[3])] << 6) | (dec[int(str[4])] << 1) | (dec[int(str[5])] >> 4); + ulid.data[3] = (dec[int(str[5])] << 4) | (dec[int(str[6])] >> 1); + ulid.data[4] = (dec[int(str[6])] << 7) | (dec[int(str[7])] << 2) | (dec[int(str[8])] >> 3); + ulid.data[5] = (dec[int(str[8])] << 5) | dec[int(str[9])]; + + // entropy + ulid.data[6] = (dec[int(str[10])] << 3) | (dec[int(str[11])] >> 2); + ulid.data[7] = (dec[int(str[11])] << 6) | (dec[int(str[12])] << 1) | (dec[int(str[13])] >> 4); + ulid.data[8] = (dec[int(str[13])] << 4) | (dec[int(str[14])] >> 1); + ulid.data[9] = (dec[int(str[14])] << 7) | (dec[int(str[15])] << 2) | (dec[int(str[16])] >> 3); + ulid.data[10] = (dec[int(str[16])] << 5) | dec[int(str[17])]; + ulid.data[11] = (dec[int(str[18])] << 3) | (dec[int(str[19])] >> 2); + ulid.data[12] = (dec[int(str[19])] << 6) | (dec[int(str[20])] << 1) | (dec[int(str[21])] >> 4); + ulid.data[13] = (dec[int(str[21])] << 4) | (dec[int(str[22])] >> 1); + ulid.data[14] = (dec[int(str[22])] << 7) | (dec[int(str[23])] << 2) | (dec[int(str[24])] >> 3); + ulid.data[15] = (dec[int(str[24])] << 5) | dec[int(str[25])]; } /** * Unmarshal will create a new ULID by unmarshaling the passed string. * */ -ULID Unmarshal(const std::string& str) { - ULID ulid; - UnmarshalFrom(str.c_str(), ulid); - return ulid; +inline ULID Unmarshal(const std::string& str) { + ULID ulid; + UnmarshalFrom(str.c_str(), ulid); + return ulid; } /** * UnmarshalBinaryFrom will unmarshal a ULID from the passed byte array. * */ -void UnmarshalBinaryFrom(const uint8_t b[16], ULID& ulid) { - // timestamp - ulid.data[0] = b[0]; - ulid.data[1] = b[1]; - ulid.data[2] = b[2]; - ulid.data[3] = b[3]; - ulid.data[4] = b[4]; - ulid.data[5] = b[5]; - - // entropy - ulid.data[6] = b[6]; - ulid.data[7] = b[7]; - ulid.data[8] = b[8]; - ulid.data[9] = b[9]; - ulid.data[10] = b[10]; - ulid.data[11] = b[11]; - ulid.data[12] = b[12]; - ulid.data[13] = b[13]; - ulid.data[14] = b[14]; - ulid.data[15] = b[15]; +inline void UnmarshalBinaryFrom(const uint8_t b[16], ULID& ulid) { + // timestamp + ulid.data[0] = b[0]; + ulid.data[1] = b[1]; + ulid.data[2] = b[2]; + ulid.data[3] = b[3]; + ulid.data[4] = b[4]; + ulid.data[5] = b[5]; + + // entropy + ulid.data[6] = b[6]; + ulid.data[7] = b[7]; + ulid.data[8] = b[8]; + ulid.data[9] = b[9]; + ulid.data[10] = b[10]; + ulid.data[11] = b[11]; + ulid.data[12] = b[12]; + ulid.data[13] = b[13]; + ulid.data[14] = b[14]; + ulid.data[15] = b[15]; } /** * Unmarshal will create a new ULID by unmarshaling the passed byte vector. * */ -ULID UnmarshalBinary(const std::vector& b) { - ULID ulid; - UnmarshalBinaryFrom(b.data(), ulid); - return ulid; +inline ULID UnmarshalBinary(const std::vector& b) { + ULID ulid; + UnmarshalBinaryFrom(b.data(), ulid); + return ulid; } /** @@ -594,106 +607,108 @@ ULID UnmarshalBinary(const std::vector& b) { * 1 if ulid1 is Lexicographically after ulid2 * 0 if ulid1 is same as ulid2 * */ -int CompareULIDs(const ULID& ulid1, const ULID& ulid2) { - // for (int i = 0 ; i < 16 ; i++) { - // if (ulid1.data[i] != ulid2.data[i]) { - // return (ulid1.data[i] < ulid2.data[i]) * -2 + 1; - // } - // } +inline int CompareULIDs(const ULID& ulid1, const ULID& ulid2) { + // for (int i = 0 ; i < 16 ; i++) { + // if (ulid1.data[i] != ulid2.data[i]) { + // return (ulid1.data[i] < ulid2.data[i]) * -2 + 1; + // } + // } - // unrolled loop + // unrolled loop - if (ulid1.data[0] != ulid2.data[0]) { - return (ulid1.data[0] < ulid2.data[0]) * -2 + 1; - } + if (ulid1.data[0] != ulid2.data[0]) { + return (ulid1.data[0] < ulid2.data[0]) * -2 + 1; + } - if (ulid1.data[1] != ulid2.data[1]) { - return (ulid1.data[1] < ulid2.data[1]) * -2 + 1; - } + if (ulid1.data[1] != ulid2.data[1]) { + return (ulid1.data[1] < ulid2.data[1]) * -2 + 1; + } - if (ulid1.data[2] != ulid2.data[2]) { - return (ulid1.data[2] < ulid2.data[2]) * -2 + 1; - } + if (ulid1.data[2] != ulid2.data[2]) { + return (ulid1.data[2] < ulid2.data[2]) * -2 + 1; + } - if (ulid1.data[3] != ulid2.data[3]) { - return (ulid1.data[3] < ulid2.data[3]) * -2 + 1; - } + if (ulid1.data[3] != ulid2.data[3]) { + return (ulid1.data[3] < ulid2.data[3]) * -2 + 1; + } - if (ulid1.data[4] != ulid2.data[4]) { - return (ulid1.data[4] < ulid2.data[4]) * -2 + 1; - } + if (ulid1.data[4] != ulid2.data[4]) { + return (ulid1.data[4] < ulid2.data[4]) * -2 + 1; + } - if (ulid1.data[5] != ulid2.data[5]) { - return (ulid1.data[5] < ulid2.data[5]) * -2 + 1; - } + if (ulid1.data[5] != ulid2.data[5]) { + return (ulid1.data[5] < ulid2.data[5]) * -2 + 1; + } - if (ulid1.data[6] != ulid2.data[6]) { - return (ulid1.data[6] < ulid2.data[6]) * -2 + 1; - } + if (ulid1.data[6] != ulid2.data[6]) { + return (ulid1.data[6] < ulid2.data[6]) * -2 + 1; + } - if (ulid1.data[7] != ulid2.data[7]) { - return (ulid1.data[7] < ulid2.data[7]) * -2 + 1; - } + if (ulid1.data[7] != ulid2.data[7]) { + return (ulid1.data[7] < ulid2.data[7]) * -2 + 1; + } - if (ulid1.data[8] != ulid2.data[8]) { - return (ulid1.data[8] < ulid2.data[8]) * -2 + 1; - } + if (ulid1.data[8] != ulid2.data[8]) { + return (ulid1.data[8] < ulid2.data[8]) * -2 + 1; + } - if (ulid1.data[9] != ulid2.data[9]) { - return (ulid1.data[9] < ulid2.data[9]) * -2 + 1; - } + if (ulid1.data[9] != ulid2.data[9]) { + return (ulid1.data[9] < ulid2.data[9]) * -2 + 1; + } - if (ulid1.data[10] != ulid2.data[10]) { - return (ulid1.data[10] < ulid2.data[10]) * -2 + 1; - } + if (ulid1.data[10] != ulid2.data[10]) { + return (ulid1.data[10] < ulid2.data[10]) * -2 + 1; + } - if (ulid1.data[11] != ulid2.data[11]) { - return (ulid1.data[11] < ulid2.data[11]) * -2 + 1; - } + if (ulid1.data[11] != ulid2.data[11]) { + return (ulid1.data[11] < ulid2.data[11]) * -2 + 1; + } - if (ulid1.data[12] != ulid2.data[12]) { - return (ulid1.data[12] < ulid2.data[12]) * -2 + 1; - } + if (ulid1.data[12] != ulid2.data[12]) { + return (ulid1.data[12] < ulid2.data[12]) * -2 + 1; + } - if (ulid1.data[13] != ulid2.data[13]) { - return (ulid1.data[13] < ulid2.data[13]) * -2 + 1; - } + if (ulid1.data[13] != ulid2.data[13]) { + return (ulid1.data[13] < ulid2.data[13]) * -2 + 1; + } - if (ulid1.data[14] != ulid2.data[14]) { - return (ulid1.data[14] < ulid2.data[14]) * -2 + 1; - } + if (ulid1.data[14] != ulid2.data[14]) { + return (ulid1.data[14] < ulid2.data[14]) * -2 + 1; + } - if (ulid1.data[15] != ulid2.data[15]) { - return (ulid1.data[15] < ulid2.data[15]) * -2 + 1; - } + if (ulid1.data[15] != ulid2.data[15]) { + return (ulid1.data[15] < ulid2.data[15]) * -2 + 1; + } - return 0; + return 0; } /** * Time will extract the timestamp used to generate a ULID * */ -time_t Time(const ULID& ulid) { - time_t ans = 0; +inline time_t Time(const ULID& ulid) { + time_t ans = 0; - ans |= ulid.data[0]; + ans |= ulid.data[0]; - ans <<= 8; - ans |= ulid.data[1]; + ans <<= 8; + ans |= ulid.data[1]; - ans <<= 8; - ans |= ulid.data[2]; + ans <<= 8; + ans |= ulid.data[2]; - ans <<= 8; - ans |= ulid.data[3]; + ans <<= 8; + ans |= ulid.data[3]; - ans <<= 8; - ans |= ulid.data[4]; + ans <<= 8; + ans |= ulid.data[4]; - ans <<= 8; - ans |= ulid.data[5]; + ans <<= 8; + ans |= ulid.data[5]; - return ans; + return ans; } }; // namespace ulid + +#endif // ULID_STRUCT_HH \ No newline at end of file diff --git a/src/ulid_uint128.h b/src/ulid_uint128.h index d912994..bf54b9e 100644 --- a/src/ulid_uint128.h +++ b/src/ulid_uint128.h @@ -1,4 +1,5 @@ -#pragma once +#ifndef ULID_UINT128_HH +#define ULID_UINT128_HH #include #include @@ -7,6 +8,8 @@ #include #include +extern long intrand(); + namespace ulid { /** @@ -18,87 +21,87 @@ typedef __uint128_t ULID; * EncodeTime will encode the first 6 bytes of a uint8_t array to the passed * timestamp * */ -void EncodeTime(time_t timestamp, ULID& ulid) { - ULID t = static_cast(timestamp >> 40); +inline void EncodeTime(time_t timestamp, ULID& ulid) { + ULID t = static_cast(timestamp >> 40); - t <<= 8; - t |= static_cast(timestamp >> 32); + t <<= 8; + t |= static_cast(timestamp >> 32); - t <<= 8; - t |= static_cast(timestamp >> 24); + t <<= 8; + t |= static_cast(timestamp >> 24); - t <<= 8; - t |= static_cast(timestamp >> 16); + t <<= 8; + t |= static_cast(timestamp >> 16); - t <<= 8; - t |= static_cast(timestamp >> 8); + t <<= 8; + t |= static_cast(timestamp >> 8); - t <<= 8; - t |= static_cast(timestamp); + t <<= 8; + t |= static_cast(timestamp); - t <<= 80; + t <<= 80; - ULID mask = 1; - mask <<= 80; - mask--; + ULID mask = 1; + mask <<= 80; + mask--; - ulid = t | (ulid & mask); + ulid = t | (ulid & mask); } /** * EncodeTimeNow will encode a ULID using the time obtained using std::time(nullptr) * */ -void EncodeTimeNow(ULID& ulid) { - EncodeTime(std::time(nullptr), ulid); +inline void EncodeTimeNow(ULID& ulid) { + EncodeTime(std::time(nullptr), ulid); } /** * EncodeTimeSystemClockNow will encode a ULID using the time obtained using * std::chrono::system_clock::now() by taking the timestamp in milliseconds. * */ -void EncodeTimeSystemClockNow(ULID& ulid) { - auto now = std::chrono::system_clock::now(); - auto ms = std::chrono::duration_cast(now.time_since_epoch()); - EncodeTime(ms.count(), ulid); +inline void EncodeTimeSystemClockNow(ULID& ulid) { + auto now = std::chrono::system_clock::now(); + auto ms = std::chrono::duration_cast(now.time_since_epoch()); + EncodeTime(ms.count(), ulid); } /** * EncodeEntropy will encode the last 10 bytes of the passed uint8_t array with * the values generated using the passed random number generator. * */ -void EncodeEntropy(const std::function& rng, ULID& ulid) { - ulid = (ulid >> 80) << 80; +inline void EncodeEntropy(const std::function& rng, ULID& ulid) { + ulid = (ulid >> 80) << 80; - ULID e = rng(); + ULID e = rng(); - e <<= 8; - e |= rng(); + e <<= 8; + e |= rng(); - e <<= 8; - e |= rng(); + e <<= 8; + e |= rng(); - e <<= 8; - e |= rng(); + e <<= 8; + e |= rng(); - e <<= 8; - e |= rng(); + e <<= 8; + e |= rng(); - e <<= 8; - e |= rng(); + e <<= 8; + e |= rng(); - e <<= 8; - e |= rng(); + e <<= 8; + e |= rng(); - e <<= 8; - e |= rng(); + e <<= 8; + e |= rng(); - e <<= 8; - e |= rng(); + e <<= 8; + e |= rng(); - e <<= 8; - e |= rng(); + e <<= 8; + e |= rng(); - ulid |= e; + ulid |= e; } /** @@ -109,118 +112,148 @@ void EncodeEntropy(const std::function& rng, ULID& ulid) { void EncodeEntropyRand(ULID& ulid) { ulid = (ulid >> 80) << 80; - ULID e = (std::rand() * 255ull) / RAND_MAX; + ULID e = (intrand() * 255ull) / RAND_MAX; e <<= 8; - e |= (std::rand() * 255ull) / RAND_MAX; + e |= (intrand() * 255ull) / RAND_MAX; e <<= 8; - e |= (std::rand() * 255ull) / RAND_MAX; + e |= (intrand() * 255ull) / RAND_MAX; e <<= 8; - e |= (std::rand() * 255ull) / RAND_MAX; + e |= (intrand() * 255ull) / RAND_MAX; e <<= 8; - e |= (std::rand() * 255ull) / RAND_MAX; + e |= (intrand() * 255ull) / RAND_MAX; e <<= 8; - e |= (std::rand() * 255ull) / RAND_MAX; + e |= (intrand() * 255ull) / RAND_MAX; e <<= 8; - e |= (std::rand() * 255ull) / RAND_MAX; + e |= (intrand() * 255ull) / RAND_MAX; e <<= 8; - e |= (std::rand() * 255ull) / RAND_MAX; + e |= (intrand() * 255ull) / RAND_MAX; e <<= 8; - e |= (std::rand() * 255ull) / RAND_MAX; + e |= (intrand() * 255ull) / RAND_MAX; e <<= 8; - e |= (std::rand() * 255ull) / RAND_MAX; + e |= (intrand() * 255ull) / RAND_MAX; + + + // ULID e = (std::rand() * 255ull) / RAND_MAX; + // + // e <<= 8; + // e |= (std::rand() * 255ull) / RAND_MAX; + // + // e <<= 8; + // e |= (std::rand() * 255ull) / RAND_MAX; + // + // e <<= 8; + // e |= (std::rand() * 255ull) / RAND_MAX; + // + // e <<= 8; + // e |= (std::rand() * 255ull) / RAND_MAX; + // + // e <<= 8; + // e |= (std::rand() * 255ull) / RAND_MAX; + // + // e <<= 8; + // e |= (std::rand() * 255ull) / RAND_MAX; + // + // e <<= 8; + // e |= (std::rand() * 255ull) / RAND_MAX; + // + // e <<= 8; + // e |= (std::rand() * 255ull) / RAND_MAX; + // + // e <<= 8; + // e |= (std::rand() * 255ull) / RAND_MAX; ulid |= e; } -std::uniform_int_distribution Distribution_0_255(0, 255); +static std::uniform_int_distribution Distribution_0_255(0, 255); /** * EncodeEntropyMt19937 will encode a ulid using std::mt19937 * * It also creates a std::uniform_int_distribution to generate values in [0, 255] * */ -void EncodeEntropyMt19937(std::mt19937& generator, ULID& ulid) { - ulid = (ulid >> 80) << 80; +inline void EncodeEntropyMt19937(std::mt19937& generator, ULID& ulid) { + ulid = (ulid >> 80) << 80; - ULID e = Distribution_0_255(generator); + ULID e = Distribution_0_255(generator); - e <<= 8; - e |= Distribution_0_255(generator); + e <<= 8; + e |= Distribution_0_255(generator); - e <<= 8; - e |= Distribution_0_255(generator); + e <<= 8; + e |= Distribution_0_255(generator); - e <<= 8; - e |= Distribution_0_255(generator); + e <<= 8; + e |= Distribution_0_255(generator); - e <<= 8; - e |= Distribution_0_255(generator); + e <<= 8; + e |= Distribution_0_255(generator); - e <<= 8; - e |= Distribution_0_255(generator); + e <<= 8; + e |= Distribution_0_255(generator); - e <<= 8; - e |= Distribution_0_255(generator); + e <<= 8; + e |= Distribution_0_255(generator); - e <<= 8; - e |= Distribution_0_255(generator); + e <<= 8; + e |= Distribution_0_255(generator); - e <<= 8; - e |= Distribution_0_255(generator); + e <<= 8; + e |= Distribution_0_255(generator); - e <<= 8; - e |= Distribution_0_255(generator); + e <<= 8; + e |= Distribution_0_255(generator); - ulid |= e; + ulid |= e; } /** * Encode will create an encoded ULID with a timestamp and a generator. * */ -void Encode(time_t timestamp, const std::function& rng, ULID& ulid) { - EncodeTime(timestamp, ulid); - EncodeEntropy(rng, ulid); +inline void Encode(time_t timestamp, const std::function& rng, ULID& ulid) { + EncodeTime(timestamp, ulid); + EncodeEntropy(rng, ulid); } /** * EncodeNowRand = EncodeTimeNow + EncodeEntropyRand. * */ -void EncodeNowRand(ULID& ulid) { - EncodeTimeNow(ulid); - EncodeEntropyRand(ulid); +inline void EncodeNowRand(ULID& ulid) { + EncodeTimeNow(ulid); + EncodeEntropyRand(ulid); } /** * Create will create a ULID with a timestamp and a generator. * */ -ULID Create(time_t timestamp, const std::function& rng) { - ULID ulid = 0; - Encode(timestamp, rng, ulid); - return ulid; +inline ULID Create(time_t timestamp, const std::function& rng) { + ULID ulid = 0; + Encode(timestamp, rng, ulid); + return ulid; } /** * CreateNowRand:EncodeNowRand = Create:Encode. * */ -ULID CreateNowRand() { - ULID ulid = 0; - EncodeNowRand(ulid); - return ulid; +inline ULID CreateNowRand() { + ULID ulid = 0; + EncodeNowRand(ulid); + return ulid; } /** * Crockford's Base32 * */ -const char Encoding[33] = "0123456789ABCDEFGHJKMNPQRSTVWXYZ"; +static const char Encoding[33] = "0123456789ABCDEFGHJKMNPQRSTVWXYZ"; /** * MarshalTo will marshal a ULID to the passed character array. @@ -243,80 +276,80 @@ const char Encoding[33] = "0123456789ABCDEFGHJKMNPQRSTVWXYZ"; * entropy: * follows similarly, except now all components are set to 5 bits. * */ -void MarshalTo(const ULID& ulid, char dst[26]) { - // 10 byte timestamp - dst[0] = Encoding[(static_cast(ulid >> 120) & 224) >> 5]; - dst[1] = Encoding[static_cast(ulid >> 120) & 31]; - dst[2] = Encoding[(static_cast(ulid >> 112) & 248) >> 3]; - dst[3] = Encoding[((static_cast(ulid >> 112) & 7) << 2) | ((static_cast(ulid >> 104) & 192) >> 6)]; - dst[4] = Encoding[(static_cast(ulid >> 104) & 62) >> 1]; - dst[5] = Encoding[((static_cast(ulid >> 104) & 1) << 4) | ((static_cast(ulid >> 96) & 240) >> 4)]; - dst[6] = Encoding[((static_cast(ulid >> 96) & 15) << 1) | ((static_cast(ulid >> 88) & 128) >> 7)]; - dst[7] = Encoding[(static_cast(ulid >> 88) & 124) >> 2]; - dst[8] = Encoding[((static_cast(ulid >> 88) & 3) << 3) | ((static_cast(ulid >> 80) & 224) >> 5)]; - dst[9] = Encoding[static_cast(ulid >> 80) & 31]; - - // 16 bytes of entropy - dst[10] = Encoding[(static_cast(ulid >> 72) & 248) >> 3]; - dst[11] = Encoding[((static_cast(ulid >> 72) & 7) << 2) | ((static_cast(ulid >> 64) & 192) >> 6)]; - dst[12] = Encoding[(static_cast(ulid >> 64) & 62) >> 1]; - dst[13] = Encoding[((static_cast(ulid >> 64) & 1) << 4) | ((static_cast(ulid >> 56) & 240) >> 4)]; - dst[14] = Encoding[((static_cast(ulid >> 56) & 15) << 1) | ((static_cast(ulid >> 48) & 128) >> 7)]; - dst[15] = Encoding[(static_cast(ulid >> 48) & 124) >> 2]; - dst[16] = Encoding[((static_cast(ulid >> 48) & 3) << 3) | ((static_cast(ulid >> 40) & 224) >> 5)]; - dst[17] = Encoding[static_cast(ulid >> 40) & 31]; - dst[18] = Encoding[(static_cast(ulid >> 32) & 248) >> 3]; - dst[19] = Encoding[((static_cast(ulid >> 32) & 7) << 2) | ((static_cast(ulid >> 24) & 192) >> 6)]; - dst[20] = Encoding[(static_cast(ulid >> 24) & 62) >> 1]; - dst[21] = Encoding[((static_cast(ulid >> 24) & 1) << 4) | ((static_cast(ulid >> 16) & 240) >> 4)]; - dst[22] = Encoding[((static_cast(ulid >> 16) & 15) << 1) | ((static_cast(ulid >> 8) & 128) >> 7)]; - dst[23] = Encoding[(static_cast(ulid >> 8) & 124) >> 2]; - dst[24] = Encoding[((static_cast(ulid >> 8) & 3) << 3) | (((static_cast(ulid)) & 224) >> 5)]; - dst[25] = Encoding[(static_cast(ulid)) & 31]; +inline void MarshalTo(const ULID& ulid, char dst[26]) { + // 10 byte timestamp + dst[0] = Encoding[(static_cast(ulid >> 120) & 224) >> 5]; + dst[1] = Encoding[static_cast(ulid >> 120) & 31]; + dst[2] = Encoding[(static_cast(ulid >> 112) & 248) >> 3]; + dst[3] = Encoding[((static_cast(ulid >> 112) & 7) << 2) | ((static_cast(ulid >> 104) & 192) >> 6)]; + dst[4] = Encoding[(static_cast(ulid >> 104) & 62) >> 1]; + dst[5] = Encoding[((static_cast(ulid >> 104) & 1) << 4) | ((static_cast(ulid >> 96) & 240) >> 4)]; + dst[6] = Encoding[((static_cast(ulid >> 96) & 15) << 1) | ((static_cast(ulid >> 88) & 128) >> 7)]; + dst[7] = Encoding[(static_cast(ulid >> 88) & 124) >> 2]; + dst[8] = Encoding[((static_cast(ulid >> 88) & 3) << 3) | ((static_cast(ulid >> 80) & 224) >> 5)]; + dst[9] = Encoding[static_cast(ulid >> 80) & 31]; + + // 16 bytes of entropy + dst[10] = Encoding[(static_cast(ulid >> 72) & 248) >> 3]; + dst[11] = Encoding[((static_cast(ulid >> 72) & 7) << 2) | ((static_cast(ulid >> 64) & 192) >> 6)]; + dst[12] = Encoding[(static_cast(ulid >> 64) & 62) >> 1]; + dst[13] = Encoding[((static_cast(ulid >> 64) & 1) << 4) | ((static_cast(ulid >> 56) & 240) >> 4)]; + dst[14] = Encoding[((static_cast(ulid >> 56) & 15) << 1) | ((static_cast(ulid >> 48) & 128) >> 7)]; + dst[15] = Encoding[(static_cast(ulid >> 48) & 124) >> 2]; + dst[16] = Encoding[((static_cast(ulid >> 48) & 3) << 3) | ((static_cast(ulid >> 40) & 224) >> 5)]; + dst[17] = Encoding[static_cast(ulid >> 40) & 31]; + dst[18] = Encoding[(static_cast(ulid >> 32) & 248) >> 3]; + dst[19] = Encoding[((static_cast(ulid >> 32) & 7) << 2) | ((static_cast(ulid >> 24) & 192) >> 6)]; + dst[20] = Encoding[(static_cast(ulid >> 24) & 62) >> 1]; + dst[21] = Encoding[((static_cast(ulid >> 24) & 1) << 4) | ((static_cast(ulid >> 16) & 240) >> 4)]; + dst[22] = Encoding[((static_cast(ulid >> 16) & 15) << 1) | ((static_cast(ulid >> 8) & 128) >> 7)]; + dst[23] = Encoding[(static_cast(ulid >> 8) & 124) >> 2]; + dst[24] = Encoding[((static_cast(ulid >> 8) & 3) << 3) | (((static_cast(ulid)) & 224) >> 5)]; + dst[25] = Encoding[(static_cast(ulid)) & 31]; } /** * Marshal will marshal a ULID to a std::string. * */ -std::string Marshal(const ULID& ulid) { - char data[27]; - data[26] = '\0'; - MarshalTo(ulid, data); - return std::string(data); +inline std::string Marshal(const ULID& ulid) { + char data[27]; + data[26] = '\0'; + MarshalTo(ulid, data); + return std::string(data); } /** * MarshalBinaryTo will Marshal a ULID to the passed byte array * */ -void MarshalBinaryTo(const ULID& ulid, uint8_t dst[16]) { - // timestamp - dst[0] = static_cast(ulid >> 120); - dst[1] = static_cast(ulid >> 112); - dst[2] = static_cast(ulid >> 104); - dst[3] = static_cast(ulid >> 96); - dst[4] = static_cast(ulid >> 88); - dst[5] = static_cast(ulid >> 80); - - // entropy - dst[6] = static_cast(ulid >> 72); - dst[7] = static_cast(ulid >> 64); - dst[8] = static_cast(ulid >> 56); - dst[9] = static_cast(ulid >> 48); - dst[10] = static_cast(ulid >> 40); - dst[11] = static_cast(ulid >> 32); - dst[12] = static_cast(ulid >> 24); - dst[13] = static_cast(ulid >> 16); - dst[14] = static_cast(ulid >> 8); - dst[15] = static_cast(ulid); +inline void MarshalBinaryTo(const ULID& ulid, uint8_t dst[16]) { + // timestamp + dst[0] = static_cast(ulid >> 120); + dst[1] = static_cast(ulid >> 112); + dst[2] = static_cast(ulid >> 104); + dst[3] = static_cast(ulid >> 96); + dst[4] = static_cast(ulid >> 88); + dst[5] = static_cast(ulid >> 80); + + // entropy + dst[6] = static_cast(ulid >> 72); + dst[7] = static_cast(ulid >> 64); + dst[8] = static_cast(ulid >> 56); + dst[9] = static_cast(ulid >> 48); + dst[10] = static_cast(ulid >> 40); + dst[11] = static_cast(ulid >> 32); + dst[12] = static_cast(ulid >> 24); + dst[13] = static_cast(ulid >> 16); + dst[14] = static_cast(ulid >> 8); + dst[15] = static_cast(ulid); } /** * MarshalBinary will Marshal a ULID to a byte vector. * */ -std::vector MarshalBinary(const ULID& ulid) { - std::vector dst(16); - MarshalBinaryTo(ulid, dst.data()); - return dst; +inline std::vector MarshalBinary(const ULID& ulid) { + std::vector dst(16); + MarshalBinaryTo(ulid, dst.data()); + return dst; } /** @@ -325,178 +358,178 @@ std::vector MarshalBinary(const ULID& ulid) { * 48-57 are digits. * 65-90 are capital alphabets. * */ -const uint8_t dec[256] = { - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - /* 0 1 2 3 4 5 6 7 */ - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - /* 8 9 */ - 0x08, 0x09, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - - /* 10(A) 11(B) 12(C) 13(D) 14(E) 15(F) 16(G) */ - 0xFF, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, - /*17(H) 18(J) 19(K) 20(M) 21(N) */ - 0x11, 0xFF, 0x12, 0x13, 0xFF, 0x14, 0x15, 0xFF, - /*22(P)23(Q)24(R) 25(S) 26(T) 27(V) 28(W) */ - 0x16, 0x17, 0x18, 0x19, 0x1A, 0xFF, 0x1B, 0x1C, - /*29(X)30(Y)31(Z) */ - 0x1D, 0x1E, 0x1F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF +static const uint8_t dec[256] = { + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + /* 0 1 2 3 4 5 6 7 */ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + /* 8 9 */ + 0x08, 0x09, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + + /* 10(A) 11(B) 12(C) 13(D) 14(E) 15(F) 16(G) */ + 0xFF, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, + /*17(H) 18(J) 19(K) 20(M) 21(N) */ + 0x11, 0xFF, 0x12, 0x13, 0xFF, 0x14, 0x15, 0xFF, + /*22(P)23(Q)24(R) 25(S) 26(T) 27(V) 28(W) */ + 0x16, 0x17, 0x18, 0x19, 0x1A, 0xFF, 0x1B, 0x1C, + /*29(X)30(Y)31(Z) */ + 0x1D, 0x1E, 0x1F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; /** * UnmarshalFrom will unmarshal a ULID from the passed character array. * */ -void UnmarshalFrom(const char str[26], ULID& ulid) { - // timestamp - ulid = (dec[int(str[0])] << 5) | dec[int(str[1])]; +inline void UnmarshalFrom(const char str[26], ULID& ulid) { + // timestamp + ulid = (dec[int(str[0])] << 5) | dec[int(str[1])]; - ulid <<= 8; - ulid |= (dec[int(str[2])] << 3) | (dec[int(str[3])] >> 2); + ulid <<= 8; + ulid |= (dec[int(str[2])] << 3) | (dec[int(str[3])] >> 2); - ulid <<= 8; - ulid |= (dec[int(str[3])] << 6) | (dec[int(str[4])] << 1) | (dec[int(str[5])] >> 4); + ulid <<= 8; + ulid |= (dec[int(str[3])] << 6) | (dec[int(str[4])] << 1) | (dec[int(str[5])] >> 4); - ulid <<= 8; - ulid |= (dec[int(str[5])] << 4) | (dec[int(str[6])] >> 1); + ulid <<= 8; + ulid |= (dec[int(str[5])] << 4) | (dec[int(str[6])] >> 1); - ulid <<= 8; - ulid |= (dec[int(str[6])] << 7) | (dec[int(str[7])] << 2) | (dec[int(str[8])] >> 3); + ulid <<= 8; + ulid |= (dec[int(str[6])] << 7) | (dec[int(str[7])] << 2) | (dec[int(str[8])] >> 3); - ulid <<= 8; - ulid |= (dec[int(str[8])] << 5) | dec[int(str[9])]; + ulid <<= 8; + ulid |= (dec[int(str[8])] << 5) | dec[int(str[9])]; - // entropy - ulid <<= 8; - ulid |= (dec[int(str[10])] << 3) | (dec[int(str[11])] >> 2); + // entropy + ulid <<= 8; + ulid |= (dec[int(str[10])] << 3) | (dec[int(str[11])] >> 2); - ulid <<= 8; - ulid |= (dec[int(str[11])] << 6) | (dec[int(str[12])] << 1) | (dec[int(str[13])] >> 4); + ulid <<= 8; + ulid |= (dec[int(str[11])] << 6) | (dec[int(str[12])] << 1) | (dec[int(str[13])] >> 4); - ulid <<= 8; - ulid |= (dec[int(str[13])] << 4) | (dec[int(str[14])] >> 1); + ulid <<= 8; + ulid |= (dec[int(str[13])] << 4) | (dec[int(str[14])] >> 1); - ulid <<= 8; - ulid |= (dec[int(str[14])] << 7) | (dec[int(str[15])] << 2) | (dec[int(str[16])] >> 3); + ulid <<= 8; + ulid |= (dec[int(str[14])] << 7) | (dec[int(str[15])] << 2) | (dec[int(str[16])] >> 3); - ulid <<= 8; - ulid |= (dec[int(str[16])] << 5) | dec[int(str[17])]; + ulid <<= 8; + ulid |= (dec[int(str[16])] << 5) | dec[int(str[17])]; - ulid <<= 8; - ulid |= (dec[int(str[18])] << 3) | (dec[int(str[19])] >> 2); + ulid <<= 8; + ulid |= (dec[int(str[18])] << 3) | (dec[int(str[19])] >> 2); - ulid <<= 8; - ulid |= (dec[int(str[19])] << 6) | (dec[int(str[20])] << 1) | (dec[int(str[21])] >> 4); + ulid <<= 8; + ulid |= (dec[int(str[19])] << 6) | (dec[int(str[20])] << 1) | (dec[int(str[21])] >> 4); - ulid <<= 8; - ulid |= (dec[int(str[21])] << 4) | (dec[int(str[22])] >> 1); + ulid <<= 8; + ulid |= (dec[int(str[21])] << 4) | (dec[int(str[22])] >> 1); - ulid <<= 8; - ulid |= (dec[int(str[22])] << 7) | (dec[int(str[23])] << 2) | (dec[int(str[24])] >> 3); + ulid <<= 8; + ulid |= (dec[int(str[22])] << 7) | (dec[int(str[23])] << 2) | (dec[int(str[24])] >> 3); - ulid <<= 8; - ulid |= (dec[int(str[24])] << 5) | dec[int(str[25])]; + ulid <<= 8; + ulid |= (dec[int(str[24])] << 5) | dec[int(str[25])]; } /** * Unmarshal will create a new ULID by unmarshaling the passed string. * */ -ULID Unmarshal(const std::string& str) { - ULID ulid; - UnmarshalFrom(str.c_str(), ulid); - return ulid; +inline ULID Unmarshal(const std::string& str) { + ULID ulid; + UnmarshalFrom(str.c_str(), ulid); + return ulid; } /** * UnmarshalBinaryFrom will unmarshal a ULID from the passed byte array. * */ -void UnmarshalBinaryFrom(const uint8_t b[16], ULID& ulid) { - // timestamp - ulid = b[0]; +inline void UnmarshalBinaryFrom(const uint8_t b[16], ULID& ulid) { + // timestamp + ulid = b[0]; - ulid <<= 8; - ulid |= b[1]; + ulid <<= 8; + ulid |= b[1]; - ulid <<= 8; - ulid |= b[2]; + ulid <<= 8; + ulid |= b[2]; - ulid <<= 8; - ulid |= b[3]; + ulid <<= 8; + ulid |= b[3]; - ulid <<= 8; - ulid |= b[4]; + ulid <<= 8; + ulid |= b[4]; - ulid <<= 8; - ulid |= b[5]; + ulid <<= 8; + ulid |= b[5]; - // entropy - ulid <<= 8; - ulid |= b[6]; + // entropy + ulid <<= 8; + ulid |= b[6]; - ulid <<= 8; - ulid |= b[7]; + ulid <<= 8; + ulid |= b[7]; - ulid <<= 8; - ulid |= b[8]; + ulid <<= 8; + ulid |= b[8]; - ulid <<= 8; - ulid |= b[9]; + ulid <<= 8; + ulid |= b[9]; - ulid <<= 8; - ulid |= b[10]; + ulid <<= 8; + ulid |= b[10]; - ulid <<= 8; - ulid |= b[11]; + ulid <<= 8; + ulid |= b[11]; - ulid <<= 8; - ulid |= b[12]; + ulid <<= 8; + ulid |= b[12]; - ulid <<= 8; - ulid |= b[13]; + ulid <<= 8; + ulid |= b[13]; - ulid <<= 8; - ulid |= b[14]; + ulid <<= 8; + ulid |= b[14]; - ulid <<= 8; - ulid |= b[15]; + ulid <<= 8; + ulid |= b[15]; } /** * Unmarshal will create a new ULID by unmarshaling the passed byte vector. * */ -ULID UnmarshalBinary(const std::vector& b) { - ULID ulid; - UnmarshalBinaryFrom(b.data(), ulid); - return ulid; +inline ULID UnmarshalBinary(const std::vector& b) { + ULID ulid; + UnmarshalBinaryFrom(b.data(), ulid); + return ulid; } /** @@ -506,34 +539,36 @@ ULID UnmarshalBinary(const std::vector& b) { * 1 if ulid1 is Lexicographically after ulid2 * 0 if ulid1 is same as ulid2 * */ -int CompareULIDs(const ULID& ulid1, const ULID& ulid2) { - return -2 * (ulid1 < ulid2) - 1 * (ulid1 == ulid2) + 1; +inline int CompareULIDs(const ULID& ulid1, const ULID& ulid2) { + return -2 * (ulid1 < ulid2) - 1 * (ulid1 == ulid2) + 1; } /** * Time will extract the timestamp used to generate a ULID * */ -time_t Time(const ULID& ulid) { - time_t ans = 0; +inline time_t Time(const ULID& ulid) { + time_t ans = 0; - ans |= static_cast(ulid >> 120); + ans |= static_cast(ulid >> 120); - ans <<= 8; - ans |= static_cast(ulid >> 112); + ans <<= 8; + ans |= static_cast(ulid >> 112); - ans <<= 8; - ans |= static_cast(ulid >> 104); + ans <<= 8; + ans |= static_cast(ulid >> 104); - ans <<= 8; - ans |= static_cast(ulid >> 96); + ans <<= 8; + ans |= static_cast(ulid >> 96); - ans <<= 8; - ans |= static_cast(ulid >> 88); + ans <<= 8; + ans |= static_cast(ulid >> 88); - ans <<= 8; - ans |= static_cast(ulid >> 80); + ans <<= 8; + ans |= static_cast(ulid >> 80); - return ans; + return ans; } }; // namespace ulid + +#endif // ULID_UINT128_HH \ No newline at end of file diff --git a/tests/test-all.R b/tests/test-all.R deleted file mode 100644 index b03e2de..0000000 --- a/tests/test-all.R +++ /dev/null @@ -1,2 +0,0 @@ -library(testthat) -test_check("ulid") diff --git a/tests/testthat/test-ulid.R b/tests/testthat/test-ulid.R deleted file mode 100644 index 0c22968..0000000 --- a/tests/testthat/test-ulid.R +++ /dev/null @@ -1,6 +0,0 @@ -context("minimal package functionality") -test_that("we can do something", { - - #expect_that(some_function(), is_a("data.frame")) - -}) diff --git a/tests/tinytest.R b/tests/tinytest.R new file mode 100644 index 0000000..1f40302 --- /dev/null +++ b/tests/tinytest.R @@ -0,0 +1,5 @@ + +if ( requireNamespace("tinytest", quietly=TRUE) ){ + tinytest::test_package("ulid") +} + diff --git a/vignettes/.gitignore b/vignettes/.gitignore new file mode 100644 index 0000000..097b241 --- /dev/null +++ b/vignettes/.gitignore @@ -0,0 +1,2 @@ +*.html +*.R diff --git a/vignettes/intro-to-ulid.Rmd b/vignettes/intro-to-ulid.Rmd new file mode 100644 index 0000000..bcc7e87 --- /dev/null +++ b/vignettes/intro-to-ulid.Rmd @@ -0,0 +1,45 @@ +--- +title: "Introduction to {ulid}" +output: rmarkdown::html_vignette +vignette: > + %\VignetteIndexEntry{Introduction to {ulid}} + %\VignetteEngine{knitr::rmarkdown} + %\VignetteEncoding{UTF-8} +--- + +```{r, include = FALSE} +knitr::opts_chunk$set( + collapse = TRUE, + comment = "#>" +) +``` + +```{r setup} +library(ulid) +``` + +### One + +```{r} +ulid::ULIDgenerate() +``` + +### Many + +```{r} +(u <- ulid::ULIDgenerate(20)) +``` + +### Unmarshal + +```{r} +unmarshal(u) +``` + +### Use defined timestamps + +```{r} +(ut <- ts_generate(as.POSIXct("2017-11-01 15:00:00", origin="1970-01-01"))) + +unmarshal(ut) +```