Current section
Files
Jump to
Current section
Files
c_src/Elixir.NetcdfNif.so
#include "erl_nif.h"
#include <netcdf.h>
#include <string.h>
#define STR_SIZE 100
// nc_create(file_name<string>) -> file_pointer<int>
static ERL_NIF_TERM nif_nc_create(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) {
int ncid;
char file_name[STR_SIZE];
// tmp
int retval;
// nc_create(FILE_NAME, NC_CLOBBER, &ncid)
// FILENAME is a string
// NC_CLOBBER is defined in #netcdf.h
// ncid is an int
if(argc != 1) {
return enif_make_badarg(env);
}
if(!enif_get_string(env, argv[0], file_name, STR_SIZE, ERL_NIF_LATIN1)) {
return enif_make_badarg(env);
}
if((retval = nc_create(file_name, NC_CLOBBER, &ncid))) {
//ERR(retval);
return enif_raise_exception(env, enif_make_int(env, retval));
}
return enif_make_int(env, ncid);
}
// nc_close(file_pointer<int>) -> nil
static ERL_NIF_TERM nif_nc_close(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) {
int ncid;
// tmp
int retval;
if(argc != 1) {
return enif_make_badarg(env);
}
if(!enif_get_int(env, argv[0], &ncid)) {
return enif_make_badarg(env);
}
if((retval = nc_close(ncid))) {
return enif_raise_exception(env, enif_make_int(env, retval));
}
return enif_make_list(env, 0);
}
// nc_def_dim(ncid<int>, name<char*>, size<int>) -> dimid<int>
static ERL_NIF_TERM nif_nc_def_dim(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) {
int ncid;
char dim_name[STR_SIZE];
int size;
int dimid;
// tmp
int retval;
if(argc != 3) {
return enif_make_badarg(env);
}
if(!enif_get_int(env, argv[0], &ncid)) {
return enif_make_badarg(env);
}
if(!enif_get_string(env, argv[1], dim_name, STR_SIZE, ERL_NIF_LATIN1)) {
return enif_make_badarg(env);
}
if(!enif_get_int(env, argv[2], &size)) {
return enif_make_badarg(env);
}
if((retval = nc_def_dim(ncid, dim_name, size, &dimid))) {
return enif_raise_exception(env, enif_make_int(env, retval));
}
return enif_make_int(env, dimid);
}
// nc_def_var(ncid<int>, name<string>, type<int>, ndims<int>, dimid<int>) -> varid<int>
static ERL_NIF_TERM nif_nc_def_var(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) {
int ncid;
char var_name[STR_SIZE];
nc_type var_type;
int ndims;
int dimid;
int varid;
// tmp
int retval;
if(argc != 5) {
return enif_make_badarg(env);
}
if(!enif_get_int(env, argv[0], &ncid)) {
return enif_make_badarg(env);
}
if(!enif_get_string(env, argv[1], var_name, STR_SIZE, ERL_NIF_LATIN1)) {
return enif_make_badarg(env);
}
if(!enif_get_int(env, argv[2], &var_type)) {
return enif_make_badarg(env);
}
if(!enif_get_int(env, argv[3], &ndims)) {
return enif_make_badarg(env);
}
if(!enif_get_int(env, argv[4], &dimid)) {
return enif_make_badarg(env);
}
if((retval = nc_def_var(ncid, var_name, var_type, ndims, &dimid, &varid))) {
return enif_raise_exception(env, enif_make_int(env, retval));
}
return enif_make_int(env, varid);
}
// nc_put_att_text(ncid<int>, varid<int>, name<string>, value<string>) -> nil
static ERL_NIF_TERM nif_nc_put_att_text(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) {
int ncid;
int varid;
char name[STR_SIZE];
char value[STR_SIZE];
// tmp
int retval;
if(argc != 4) {
return enif_make_badarg(env);
}
if(!enif_get_int(env, argv[0], &ncid)) {
return enif_make_badarg(env);
}
if(!enif_get_int(env, argv[1], &varid)) {
return enif_make_badarg(env);
}
if(!enif_get_string(env, argv[2], name, STR_SIZE, ERL_NIF_LATIN1)) {
return enif_make_badarg(env);
}
if(!enif_get_string(env, argv[3], value, STR_SIZE, ERL_NIF_LATIN1)) {
return enif_make_badarg(env);
}
if((retval = nc_put_att_text(ncid, varid, name, strlen(value), value))) {
return enif_raise_exception(env, enif_make_int(env, retval));
}
return enif_make_list(env, 0);
}
// nc_enddef(ncid<int>) -> nil
static ERL_NIF_TERM nif_nc_enddef(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) {
int ncid;
// tmp
int retval;
if(argc != 1) {
return enif_make_badarg(env);
}
if(!enif_get_int(env, argv[0], &ncid)) {
return enif_make_badarg(env);
}
if((retval = nc_enddef(ncid))) {
return enif_raise_exception(env, enif_make_int(env, retval));
}
return enif_make_list(env, 0);
}
// put a SINGLE float value into the variable
// nc_put_var_double_single(ncid<int>, varid<int>, values<float>) -> nil
static ERL_NIF_TERM nif_nc_put_var_double_single(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) {
int ncid;
int varid;
double value[1];
// tmp
int retval;
if(argc != 3) {
return enif_make_badarg(env);
}
if(!enif_get_int(env, argv[0], &ncid)) {
return enif_make_badarg(env);
}
if(!enif_get_int(env, argv[1], &varid)) {
return enif_make_badarg(env);
}
if(!enif_get_double(env, argv[2], &value[0])) {
return enif_make_badarg(env);
}
if((retval = nc_put_var_double(ncid, varid, &value[0]))) {
return enif_raise_exception(env, enif_make_int(env, retval));
}
return enif_make_list(env, 0);
}
// TODO WIP (finish list iteration)
static ERL_NIF_TERM nif_nc_put_var_double(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) {
int ncid;
int varid;
unsigned size;
double* value;
ERL_NIF_TERM list;
ERL_NIF_TERM head;
ERL_NIF_TERM tail;
// tmp
int retval;
if(argc != 3) {
return enif_make_badarg(env);
}
if(!enif_get_int(env, argv[0], &ncid)) {
return enif_make_badarg(env);
}
if(!enif_get_int(env, argv[1], &varid)) {
return enif_make_badarg(env);
}
// convert the list of erl values to a list of doubles
list = argv[2];
if(!enif_get_list_length(env, list, &size)) {
return enif_make_badarg(env);
}
if(size == 0) {
// list is empty, nothing to do
return enif_make_list(env, 0);
}
value = malloc(sizeof(double) * size);
for(int i = 0; i < size; i++) {
// printf("Loop: i = %d\n", i);
// take head and tail of the list
if(!enif_get_list_cell(env, list, &head, &tail)) {
return enif_make_badarg(env);
}
if(!enif_get_double(env, head, &value[i])) {
return enif_make_badarg(env);
}
list = tail;
}
if((retval = nc_put_var_double(ncid, varid, &value[0]))) {
return enif_raise_exception(env, enif_make_int(env, retval));
}
free(value);
return enif_make_list(env, 0);
}
static ErlNifFunc nif_funcs[] = {
{"nc_create", 1, nif_nc_create},
{"nc_close", 1, nif_nc_close},
{"nc_def_dim", 3, nif_nc_def_dim},
{"nc_def_var", 5, nif_nc_def_var},
{"nc_put_att_text", 4, nif_nc_put_att_text},
{"nc_enddef", 1, nif_nc_enddef},
{"nc_put_var_double_single", 3, nif_nc_put_var_double_single},
{"nc_put_var_double", 3, nif_nc_put_var_double}
};
ERL_NIF_INIT(Elixir.NetcdfNif,nif_funcs,NULL,NULL,NULL,NULL);