// 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 #include #include #include #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); }