#include #include #include #define RUAPU_IMPLEMENTATION #include "ruapu.h" ERL_NIF_TERM atom(ErlNifEnv *env, const char *msg) { ERL_NIF_TERM a; if (enif_make_existing_atom(env, msg, &a, ERL_NIF_LATIN1)) { return a; } else { return enif_make_atom(env, msg); } } ERL_NIF_TERM error(ErlNifEnv *env, const char *msg) { ERL_NIF_TERM error_atom = atom(env, "error"); ERL_NIF_TERM msg_term = enif_make_string(env, msg, ERL_NIF_LATIN1); return enif_make_tuple2(env, error_atom, msg_term); } ERL_NIF_TERM ok(ErlNifEnv *env) { return atom(env, "ok"); } ERL_NIF_TERM ok_tuple(ErlNifEnv *env, ERL_NIF_TERM term) { return enif_make_tuple2(env, atom(env, "ok"), term); } const char *get_string(ErlNifEnv *env, ERL_NIF_TERM term) { char *result = NULL; unsigned len; int ret = enif_get_list_length(env, term, &len); if (ret) { result = (char *)enif_alloc(sizeof(char) * (len + 1)); ret = enif_get_string(env, term, result, len + 1, ERL_NIF_LATIN1); if (ret > 0) { return result; } else { enif_free((void *)result); return NULL; } } ErlNifBinary bin; ret = enif_inspect_binary(env, term, &bin); if (ret) { result = (char *)enif_alloc(sizeof(char) * (bin.size + 1)); if (result == NULL) { return NULL; } memcpy(result, bin.data, bin.size); result[bin.size] = '\0'; return result; } ret = enif_get_atom_length(env, term, &len, ERL_NIF_LATIN1); if (ret) { result = (char *)enif_alloc(sizeof(char) * (len + 1)); ret = enif_get_atom(env, term, result, len + 1, ERL_NIF_LATIN1); if (ret) { return result; } else { enif_free((void *)result); return NULL; } } return NULL; } static ERL_NIF_TERM nif_supports(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) { const char *isa = get_string(env, argv[0]); if (isa == NULL) { return enif_make_badarg(env); } int supports = ruapu_supports(isa); enif_free((void *)isa); if (supports) { return atom(env, "true"); } else { return atom(env, "false"); } } static ERL_NIF_TERM nif_rua(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) { const char *const *supported = ruapu_rua(); const char *const *supported_start = supported; uint32_t count = 0; while (*supported_start) { supported_start++; count++; } if (count == 0) { ERL_NIF_TERM list = enif_make_list(env, 0, NULL); return ok_tuple(env, list); } ERL_NIF_TERM *terms = (ERL_NIF_TERM *)enif_alloc(sizeof(ERL_NIF_TERM) * count); if (terms == NULL) { return error(env, "enif_alloc failed"); } supported_start = supported; for (uint32_t i = 0; i < count; i++) { terms[i] = enif_make_string(env, *supported_start, ERL_NIF_LATIN1); supported_start++; } ERL_NIF_TERM list = enif_make_list_from_array(env, terms, count); enif_free(terms); return ok_tuple(env, list); } static int on_load(ErlNifEnv *env, void **_sth1, ERL_NIF_TERM _sth2) { ruapu_init(); return 0; } static int on_reload(ErlNifEnv *_sth0, void **_sth1, ERL_NIF_TERM _sth2) { return 0; } static int on_upgrade(ErlNifEnv *_sth0, void **_sth1, void **_sth2, ERL_NIF_TERM _sth3) { return 0; } static ErlNifFunc nif_functions[] = { {"supports", 1, nif_supports, ERL_NIF_DIRTY_JOB_CPU_BOUND}, {"rua", 0, nif_rua, ERL_NIF_DIRTY_JOB_CPU_BOUND}, }; ERL_NIF_INIT(ruapu_nif, nif_functions, on_load, on_reload, on_upgrade, NULL);