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.
rngxx/src/capi.c

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);
}