Current section

Files

Jump to
crc c_src nif crc_16_dnp.c
Raw

c_src/nif/crc_16_dnp.c

// -*- mode: c++; tab-width: 4; indent-tabs-mode: nil; st-rulers: [132] -*-
// vim: ts=4 sw=4 ft=c++ et
#include "crc_16.h"
#include "xnif_slice.h"
static const uint16_t crc_16_dnp_table[256] = {
0x0000, 0x365e, 0x6cbc, 0x5ae2, 0xd978, 0xef26, 0xb5c4, 0x839a, 0xff89, 0xc9d7, 0x9335, 0xa56b, 0x26f1, 0x10af, 0x4a4d, 0x7c13,
0xb26b, 0x8435, 0xded7, 0xe889, 0x6b13, 0x5d4d, 0x07af, 0x31f1, 0x4de2, 0x7bbc, 0x215e, 0x1700, 0x949a, 0xa2c4, 0xf826, 0xce78,
0x29af, 0x1ff1, 0x4513, 0x734d, 0xf0d7, 0xc689, 0x9c6b, 0xaa35, 0xd626, 0xe078, 0xba9a, 0x8cc4, 0x0f5e, 0x3900, 0x63e2, 0x55bc,
0x9bc4, 0xad9a, 0xf778, 0xc126, 0x42bc, 0x74e2, 0x2e00, 0x185e, 0x644d, 0x5213, 0x08f1, 0x3eaf, 0xbd35, 0x8b6b, 0xd189, 0xe7d7,
0x535e, 0x6500, 0x3fe2, 0x09bc, 0x8a26, 0xbc78, 0xe69a, 0xd0c4, 0xacd7, 0x9a89, 0xc06b, 0xf635, 0x75af, 0x43f1, 0x1913, 0x2f4d,
0xe135, 0xd76b, 0x8d89, 0xbbd7, 0x384d, 0x0e13, 0x54f1, 0x62af, 0x1ebc, 0x28e2, 0x7200, 0x445e, 0xc7c4, 0xf19a, 0xab78, 0x9d26,
0x7af1, 0x4caf, 0x164d, 0x2013, 0xa389, 0x95d7, 0xcf35, 0xf96b, 0x8578, 0xb326, 0xe9c4, 0xdf9a, 0x5c00, 0x6a5e, 0x30bc, 0x06e2,
0xc89a, 0xfec4, 0xa426, 0x9278, 0x11e2, 0x27bc, 0x7d5e, 0x4b00, 0x3713, 0x014d, 0x5baf, 0x6df1, 0xee6b, 0xd835, 0x82d7, 0xb489,
0xa6bc, 0x90e2, 0xca00, 0xfc5e, 0x7fc4, 0x499a, 0x1378, 0x2526, 0x5935, 0x6f6b, 0x3589, 0x03d7, 0x804d, 0xb613, 0xecf1, 0xdaaf,
0x14d7, 0x2289, 0x786b, 0x4e35, 0xcdaf, 0xfbf1, 0xa113, 0x974d, 0xeb5e, 0xdd00, 0x87e2, 0xb1bc, 0x3226, 0x0478, 0x5e9a, 0x68c4,
0x8f13, 0xb94d, 0xe3af, 0xd5f1, 0x566b, 0x6035, 0x3ad7, 0x0c89, 0x709a, 0x46c4, 0x1c26, 0x2a78, 0xa9e2, 0x9fbc, 0xc55e, 0xf300,
0x3d78, 0x0b26, 0x51c4, 0x679a, 0xe400, 0xd25e, 0x88bc, 0xbee2, 0xc2f1, 0xf4af, 0xae4d, 0x9813, 0x1b89, 0x2dd7, 0x7735, 0x416b,
0xf5e2, 0xc3bc, 0x995e, 0xaf00, 0x2c9a, 0x1ac4, 0x4026, 0x7678, 0x0a6b, 0x3c35, 0x66d7, 0x5089, 0xd313, 0xe54d, 0xbfaf, 0x89f1,
0x4789, 0x71d7, 0x2b35, 0x1d6b, 0x9ef1, 0xa8af, 0xf24d, 0xc413, 0xb800, 0x8e5e, 0xd4bc, 0xe2e2, 0x6178, 0x5726, 0x0dc4, 0x3b9a,
0xdc4d, 0xea13, 0xb0f1, 0x86af, 0x0535, 0x336b, 0x6989, 0x5fd7, 0x23c4, 0x159a, 0x4f78, 0x7926, 0xfabc, 0xcce2, 0x9600, 0xa05e,
0x6e26, 0x5878, 0x029a, 0x34c4, 0xb75e, 0x8100, 0xdbe2, 0xedbc, 0x91af, 0xa7f1, 0xfd13, 0xcb4d, 0x48d7, 0x7e89, 0x246b, 0x1235};
uint16_t
crc_16_dnp_init(void)
{
return 0x0000;
}
uint16_t
crc_16_dnp_update(uint16_t ctx, const unsigned char *buf, size_t len)
{
while (len--) {
ctx = (ctx >> 8) ^ crc_16_dnp_table[(ctx ^ (uint16_t)*buf++) & 0x00FF];
}
return ctx;
}
uint16_t
crc_16_dnp_final(uint16_t ctx)
{
uint16_t low_byte;
uint16_t high_byte;
ctx = ~ctx;
low_byte = (ctx & 0xFF00) >> 8;
high_byte = (ctx & 0x00FF) << 8;
ctx = low_byte | high_byte;
return ctx;
}
/* NIF Functions */
static int crc_nif_crc_16_dnp_1_work(ErlNifEnv *env, xnif_slice_t *slice, int *phasep, size_t *offsetp, size_t reductions);
static ERL_NIF_TERM crc_nif_crc_16_dnp_1_done(ErlNifEnv *env, xnif_slice_t *slice);
static xnif_slice_func_t crc_nif_crc_16_dnp_1_func = {
crc_nif_crc_16_dnp_1_work, crc_nif_crc_16_dnp_1_done, NULL, NULL,
};
ERL_NIF_TERM
crc_nif_crc_16_dnp_1(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
{
ErlNifBinary input;
if (argc != 1 || !enif_inspect_binary(env, argv[0], &input)) {
return enif_make_badarg(env);
}
if (input.size <= XNIF_SLICE_MAX_PER_SLICE) {
uint16_t crc;
crc = crc_16_dnp(input.data, input.size);
return enif_make_uint(env, crc);
}
xnif_slice_t *slice = xnif_slice_create("crc_16_dnp", &crc_nif_crc_16_dnp_1_func, 0, input.size);
if (slice == NULL) {
return enif_make_badarg(env);
}
uint16_t ctx = crc_16_dnp_init();
ERL_NIF_TERM newargv[2];
newargv[0] = enif_make_uint(env, ctx);
newargv[1] = argv[0];
return xnif_slice_schedule(env, slice, 2, newargv);
}
static int
crc_nif_crc_16_dnp_1_work(ErlNifEnv *env, xnif_slice_t *slice, int *phasep, size_t *offsetp, size_t reductions)
{
size_t offset = *offsetp;
uint16_t ctx;
ErlNifBinary input;
if (slice->argc != 2 || !enif_get_uint(env, slice->argv[0], (unsigned int *)&ctx) ||
!enif_inspect_binary(env, slice->argv[1], &input)) {
return -1;
}
ctx = crc_16_dnp_update(ctx, input.data + offset, reductions);
slice->argv[0] = enif_make_uint(env, ctx);
*offsetp = offset + reductions;
return 0;
}
static ERL_NIF_TERM
crc_nif_crc_16_dnp_1_done(ErlNifEnv *env, xnif_slice_t *slice)
{
uint16_t ctx;
if (slice->argc != 2 || !enif_get_uint(env, slice->argv[0], (unsigned int *)&ctx)) {
return enif_make_badarg(env);
}
return enif_make_uint(env, crc_16_dnp_final(ctx));
}
ERL_NIF_TERM
crc_nif_crc_16_dnp_init_0(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
{
if (argc != 0) {
return enif_make_badarg(env);
}
uint16_t ctx = crc_16_dnp_init();
return enif_make_uint(env, ctx);
}
static int crc_nif_crc_16_dnp_update_2_work(ErlNifEnv *env, xnif_slice_t *slice, int *phasep, size_t *offsetp, size_t reductions);
static ERL_NIF_TERM crc_nif_crc_16_dnp_update_2_done(ErlNifEnv *env, xnif_slice_t *slice);
static xnif_slice_func_t crc_nif_crc_16_dnp_update_2_func = {
crc_nif_crc_16_dnp_update_2_work, crc_nif_crc_16_dnp_update_2_done, NULL, NULL,
};
ERL_NIF_TERM
crc_nif_crc_16_dnp_update_2(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
{
unsigned int ctx;
ErlNifBinary input;
if (argc != 2 || !enif_get_uint(env, argv[0], &ctx) || ctx > 0xffff || !enif_inspect_binary(env, argv[1], &input)) {
return enif_make_badarg(env);
}
if (input.size <= XNIF_SLICE_MAX_PER_SLICE) {
ctx = crc_16_dnp_update((uint16_t)ctx, input.data, input.size);
return enif_make_uint(env, ctx);
}
xnif_slice_t *slice = xnif_slice_create("crc_16_dnp_update", &crc_nif_crc_16_dnp_update_2_func, 0, input.size);
if (slice == NULL) {
return enif_make_badarg(env);
}
ERL_NIF_TERM newargv[2];
newargv[0] = argv[0];
newargv[1] = argv[1];
return xnif_slice_schedule(env, slice, 2, newargv);
}
static int
crc_nif_crc_16_dnp_update_2_work(ErlNifEnv *env, xnif_slice_t *slice, int *phasep, size_t *offsetp, size_t reductions)
{
size_t offset = *offsetp;
uint16_t ctx;
ErlNifBinary input;
if (slice->argc != 2 || !enif_get_uint(env, slice->argv[0], (unsigned int *)&ctx) ||
!enif_inspect_binary(env, slice->argv[1], &input)) {
return -1;
}
ctx = crc_16_dnp_update(ctx, input.data + offset, reductions);
slice->argv[0] = enif_make_uint(env, ctx);
*offsetp = offset + reductions;
return 0;
}
static ERL_NIF_TERM
crc_nif_crc_16_dnp_update_2_done(ErlNifEnv *env, xnif_slice_t *slice)
{
uint16_t ctx;
if (slice->argc != 2 || !enif_get_uint(env, slice->argv[0], (unsigned int *)&ctx)) {
return enif_make_badarg(env);
}
return enif_make_uint(env, ctx);
}
ERL_NIF_TERM
crc_nif_crc_16_dnp_final_1(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
{
unsigned int ctx;
if (argc != 1 || !enif_get_uint(env, argv[0], &ctx) || ctx > 0xffff) {
return enif_make_badarg(env);
}
uint16_t crc = crc_16_dnp_final((uint16_t)ctx);
return enif_make_uint(env, crc);
}