You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
123 lines
3.1 KiB
123 lines
3.1 KiB
// Contains the library exported C API functions.
|
|
// Actual work may be done in `capi-bridge.cpp`, `capi-bridge.h` bridges this shim TU with that working one
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
|
|
#include <common.h>
|
|
#include <rngxx.h>
|
|
|
|
#include "capi-bridge.h"
|
|
|
|
#define assert_not_null(expr, ...) ({ __auto_type _nn__expr = (expr); \
|
|
if(UNLIKELY(_nn__expr == NULL)) { fprintf(stderr, "fatal (unexpected null pointer): " __VA_ARGS__); abort(); } \
|
|
_nn__expr; })
|
|
|
|
rng_t* rng_new(enum rng_kind kind, const u64 seed[static restrict 1])
|
|
{
|
|
return assert_not_null(RNG_IMPL(mkdriver) (kind, &seed[0]), "invalid kind %d", (int)kind);
|
|
}
|
|
// void rng_free() - direct bridge
|
|
|
|
int rng_raw(rng_t* engine, void* restrict output, struct rng_next_opt opt)
|
|
{
|
|
return RNG_IMPL(mnext)(engine, output, &opt);
|
|
}
|
|
|
|
void rng_next_bin(rng_t* engine, unsigned char* restrict output, size_t n)
|
|
{
|
|
RNG_IMPL(mnext)(engine, (void* restrict)output, &(struct rng_next_opt){
|
|
.bound.len = n,
|
|
.ty.type = RNG_TY_BLOB,
|
|
});
|
|
}
|
|
|
|
static void* m_alloc_for(enum rng_next_type ty)
|
|
{
|
|
size_t s, a;
|
|
switch( RNG_IMPL(m_allocsz_for)(ty, &s, &a) )
|
|
{
|
|
case 2: // size 0, align nonzero
|
|
case 0: break;
|
|
case 1: return malloc(s);
|
|
case 3: return aligned_alloc(a, s);
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
static void* m_alloc_array(enum rng_next_type ty, size_t ars)
|
|
{
|
|
size_t s, a;
|
|
switch( RNG_IMPL(m_allocsz_for)(ty, &s, &a) )
|
|
{
|
|
case 2: // size 0, align nonzero
|
|
case 0: break;
|
|
case 1: return calloc(ars, s);
|
|
case 3: return aligned_alloc(a, s * ars);
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
void* rng_next_tyab(rng_t* engine, void* restrict output, enum rng_next_type ty, enum rng_next_flag flags, uint32_t sz, const void* pmin, const void* pmax)
|
|
{
|
|
if(!sz) return output;
|
|
if(! (output = output ?: m_alloc_array(ty, (size_t)sz)) ) return NULL;
|
|
|
|
RNG_IMPL(mnext)(engine, output, &(struct rng_next_opt){
|
|
.bound.range = { pmin, pmax },
|
|
.ty = {
|
|
.type = ty,
|
|
.mod = flags | (sz > 1 ? RNG_TYQ_ARRAY : 0 ),
|
|
},
|
|
.ex = {
|
|
.array_size = sz,
|
|
},
|
|
});
|
|
return output;
|
|
|
|
}
|
|
void* rng_next_tyb(rng_t* engine, void* restrict output, enum rng_next_type ty, enum rng_next_flag flags, const void* pmin, const void* pmax)
|
|
{
|
|
if(! ( output = output ?: m_alloc_for(ty)) ) return NULL;
|
|
|
|
RNG_IMPL(mnext)(engine, output, &(struct rng_next_opt){
|
|
.bound.range = {
|
|
.pmin = pmin,
|
|
.pmax = pmax,
|
|
},
|
|
.ty = {
|
|
.type = ty,
|
|
.mod = flags,
|
|
},
|
|
.ex = {0},
|
|
});
|
|
|
|
return output;
|
|
}
|
|
|
|
void* rng_next_ty(rng_t* engine, void* restrict output, enum rng_next_type ty, enum rng_next_flag flags)
|
|
{
|
|
return rng_next_tyb(engine, output, ty, flags, NULL, NULL);
|
|
}
|
|
|
|
void* rng_next_tya(rng_t* engine, void* restrict output, enum rng_next_type ty, enum rng_next_flag flags, uint32_t sz)
|
|
{
|
|
if(!sz) return output;
|
|
return rng_next_tyab(engine, output, ty, flags, sz, NULL, NULL);
|
|
}
|
|
|
|
rng_t* rng_new_named(const char* name, const void* seed)
|
|
{
|
|
return RNG_IMPL(dynctor_trycall)(name, seed);
|
|
}
|
|
|
|
rng_dyn_ctor_ref rng_ctor_ref(const char* name)
|
|
{
|
|
return RNG_IMPL(dynctor_refer)(name);
|
|
}
|
|
|
|
rng_t* rng_ctor_call(rng_dyn_ctor_ref ctor, const void* seed)
|
|
{
|
|
return RNG_IMPL(dynctor_callref)(ctor, seed);
|
|
}
|