Skip to content

Commit

Permalink
library/system: Generate UUIDs with libuuid instead
Browse files Browse the repository at this point in the history
  • Loading branch information
lhmouse committed Mar 7, 2024
1 parent 6229a86 commit 340018f
Show file tree
Hide file tree
Showing 4 changed files with 21 additions and 71 deletions.
64 changes: 11 additions & 53 deletions asteria/library/system.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
#include <sys/utsname.h> // ::uname()
#include <sys/socket.h> // ::socket()
#include <time.h> // ::clock_gettime()
#include <uuid/uuid.h> // ::uuid_generate_random()
extern char **environ;
namespace asteria {
namespace {
Expand Down Expand Up @@ -305,56 +306,13 @@ std_system_get_properties()
}

V_string
std_system_generate_uuid(Global_Context& global)
std_system_random_uuid()
{
// Canonical form: `xxxxxxxx-xxxx-Myyy-Nzzz-wwwwwwwwwwww`
// * x: number of 1/30518 seconds since UNIX Epoch
// * M: always `4` (UUID version)
// * y: process ID
// * N: any of `0`-`7` (UUID variant)
// * z: context ID
// * w: random bytes
static atomic<uint64_t> serial;
const auto prng = global.random_engine();

::timespec ts;
::clock_gettime(CLOCK_REALTIME, &ts);

uint64_t x = (uint64_t) ts.tv_sec * 30518U + (uint32_t) ts.tv_nsec / 32768U + serial.xadd(1U);
uint64_t y = (uint32_t) ::getpid();
uint64_t z = (uint64_t)(void*) &global >> 12;
uint64_t w = (uint64_t) prng->bump() << 32 | prng->bump();

// Set version and variant.
y &= 0x0FFF;
y |= 0x4000;
z &= 0x7FFF;

// Compose the UUID string.
cow_string str;
auto wpos = str.insert(str.begin(), 36, '-');

auto put_hex_uint16 = [&](uint64_t value)
{
uint32_t ch;
for(int k = 3; k >= 0; --k)
ch = (uint32_t) (value >> k * 4) & 0x0F,
*(wpos++) = (char) ('0' + ch + ((9 - ch) >> 29));
};

put_hex_uint16(x >> 32);
put_hex_uint16(x >> 16);
wpos++;
put_hex_uint16(x);
wpos++;
put_hex_uint16(y);
wpos++;
put_hex_uint16(z);
wpos++;
put_hex_uint16(w >> 32);
put_hex_uint16(w >> 32);
put_hex_uint16(w);
return str;
::uuid_t uuid;
::uuid_generate_random(uuid);
char str[37];
::uuid_unparse_lower(uuid, str);
return V_string(str, 36);
}

V_integer
Expand Down Expand Up @@ -600,14 +558,14 @@ create_bindings_system(V_object& result, API_Version /*version*/)
reader.throw_no_matching_function_call();
});

result.insert_or_assign(&"generate_uuid",
result.insert_or_assign(&"random_uuid",
ASTERIA_BINDING(
"std.system.generate_uuid", "",
Global_Context& global, Argument_Reader&& reader)
"std.system.random_uuid", "",
Argument_Reader&& reader)
{
reader.start_overload();
if(reader.end_overload())
return (Value) std_system_generate_uuid(global);
return (Value) std_system_random_uuid();

reader.throw_no_matching_function_call();
});
Expand Down
4 changes: 2 additions & 2 deletions asteria/library/system.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,9 @@ std_system_get_environment_variables();
V_object
std_system_get_properties();

// `std.system.generate_uuid`
// `std.system.random_uuid`
V_string
std_system_generate_uuid(Global_Context& global);
std_system_random_uuid();

// `std.system.get_pid()`
V_integer
Expand Down
19 changes: 5 additions & 14 deletions doc/standard-library.md
Original file line number Diff line number Diff line change
Expand Up @@ -90,21 +90,12 @@ variable. Individual components are categorized into sub-objects.
* `arch` string: name of the CPU architecture
* `nprocs` integer: number of active CPU cores

### `std.system.generate_uuid()`
### `std.system.random_uuid()`

* Generates a UUID of the form `xxxxxxxx-xxxx-Myyy-Nzzz-wwwwwwwwwwww`, where

* x: number of 1/30518 seconds since UNIX Epoch
* M: always `4` (UUID version)
* y: process ID
* N: any of `0`-`7` (UUID variant)
* z: context ID
* w: random bytes

Unlike version-1 UUIDs in RFC 4122, the timestamp is written in big-endian
byte order. This ensures the (case-insensitive) lexicographical ordering of
such UUIDs match their order of creation. Hexadecimal digits above nine are
encoded as capital letters.
* Generates a random UUID of the form `xxxxxxxx-xxxx-Mxxx-Nxxx-xxxxxxxxxxxx`,
where `M` is always `4` (UUID version) and `N` is any of `8`-`f` (UUID
variant), and the others are random bits. Hexadecimal digits above nine are
encoded in lowercase.

* Returns a UUID as a string of 36 characters, without braces.

Expand Down
5 changes: 3 additions & 2 deletions meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -355,7 +355,8 @@ add_project_arguments(
dep_zlib = dependency('zlib', version: '>= 1.2.9')
dep_pcre2 = dependency('libpcre2-8')
dep_openssl = dependency('openssl')
dep_iconv = dependency('iconv', required: false)
dep_iconv = dependency('iconv')
dep_uuid = dependency('uuid')
dep_editline = disabler()

if get_option('enable-repl')
Expand All @@ -382,7 +383,7 @@ install_headers(meson.current_build_dir() / 'version.h', subdir: 'asteria')
lib_asteria = both_libraries('asteria',
cpp_pch: 'asteria/xprecompiled.hpp',
sources: asteria_src,
dependencies: [ dep_zlib, dep_pcre2, dep_openssl, dep_iconv ],
dependencies: [ dep_zlib, dep_pcre2, dep_openssl, dep_iconv, dep_uuid ],
soversion: ver.get('abi_major'),
version: '.'.join([ ver.get('abi_major'), ver.get('abi_minor'), '0' ]),
install: true)
Expand Down

0 comments on commit 340018f

Please sign in to comment.