ERL_NIF_TERM _hh_max(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
    hh_ctx_t* ctx = NULL;

    ErlNifResourceType* ctx_type = get_hh_ctx_type(env);
    if (argc != 1 ||
        ctx_type == NULL ||
        !enif_get_resource(env, argv[0], ctx_type, (void **)&ctx) ||
        ctx->data == NULL)
    {
        return enif_make_badarg(env);
    }
   
    if (ctx != NULL)
    {
        if (ctx->data->total_count == 0)
        {
            return enif_make_int64(env, 0);
        }
        else
        {
            return enif_make_int64(env, hdr_max(ctx->data));
        }
    }

    return make_error(env, "bad_hdr_histogram_nif_impl");
}
Exemple #2
0
ERL_NIF_TERM entry_to_term(ErlNifEnv *env, const git_index_entry *entry)
{
	ErlNifBinary id, path;
	size_t len;

	if (geef_oid_bin(&id, &entry->id) < 0)
		return geef_oom(env);

	len = strlen(entry->path);
	if (!enif_alloc_binary(len, &path)) {
		enif_release_binary(&id);
		return geef_oom(env);
	}
	memcpy(path.data, entry->path, len);

	return enif_make_tuple(env, 13, atoms.ok,
			       enif_make_int64(env, entry->ctime.seconds),
			       enif_make_int64(env, entry->mtime.seconds),
			       enif_make_uint(env, entry->dev),
			       enif_make_uint(env, entry->ino),
			       enif_make_uint(env, entry->mode),
			       enif_make_uint(env, entry->uid),
			       enif_make_uint(env, entry->gid),
			       enif_make_int64(env, entry->file_size),
			       enif_make_binary(env, &id),
			       enif_make_uint(env, entry->flags),
			       enif_make_uint(env, entry->flags_extended),
			       enif_make_binary(env, &path));
}
Exemple #3
0
static ERL_NIF_TERM read_info_nif(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) {
    posix_errno_t posix_errno;

    efile_fileinfo_t info = {0};
    efile_path_t path;
    int follow_links;

    if(argc != 2 || !enif_get_int(env, argv[1], &follow_links)) {
        return enif_make_badarg(env);
    }

    if((posix_errno = efile_marshal_path(env, argv[0], &path))) {
        return posix_error_to_tuple(env, posix_errno);
    } else if((posix_errno = efile_read_info(&path, follow_links, &info))) {
        return posix_error_to_tuple(env, posix_errno);
    }

    /* #file_info as declared in file.hrl */
    return enif_make_tuple(env, 14,
        am_file_info,
        enif_make_uint64(env, info.size),
        efile_filetype_to_atom(info.type),
        efile_access_to_atom(info.access),
        enif_make_int64(env, MAX(EFILE_MIN_FILETIME, info.a_time)),
        enif_make_int64(env, MAX(EFILE_MIN_FILETIME, info.m_time)),
        enif_make_int64(env, MAX(EFILE_MIN_FILETIME, info.c_time)),
        enif_make_uint(env, info.mode),
        enif_make_uint(env, info.links),
        enif_make_uint(env, info.major_device),
        enif_make_uint(env, info.minor_device),
        enif_make_uint(env, info.inode),
        enif_make_uint(env, info.uid),
        enif_make_uint(env, info.gid)
    );
}
Exemple #4
0
ERL_NIF_TERM x_pool_lookup(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
    uint64_t id;
    char pool_name[MAX_NAME_LEN];
    if (!enif_get_uint64(env, argv[0], &id) ||
        !enif_get_string(env, argv[1], pool_name, MAX_NAME_LEN, ERL_NIF_LATIN1))
    {
        return enif_make_badarg(env);
    }

    rados_t cluster = map_cluster_get(id);
    if (cluster == NULL)
    {
        return enif_make_badarg(env);
    }

    int64_t err = rados_pool_lookup(cluster, pool_name);
    if (err < 0) 
    {
        return make_error_tuple(env, -err);
    }

    return enif_make_tuple2(env,
                            enif_make_atom(env, "ok"),
                            enif_make_int64(env, err));  // Pool ID
}
Exemple #5
0
/* 0: socket, 1: buffer, 2: flags, 3: struct sockaddr */
    static ERL_NIF_TERM
nif_sendto(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
{
    int sockfd = -1;
    int flags = 0;
    ssize_t n = 0;

    ErlNifBinary buf = {0};
    ErlNifBinary sa = {0};

    if (!enif_get_int(env, argv[0], &sockfd))
        return enif_make_badarg(env);

    if (!enif_inspect_binary(env, argv[1], &buf))
        return enif_make_badarg(env);

    if (!enif_get_int(env, argv[2], &flags))
        return enif_make_badarg(env);

    if (!enif_inspect_binary(env, argv[3], &sa))
        return enif_make_badarg(env);

    n = sendto(sockfd, buf.data, buf.size, flags,
            (sa.size == 0 ? NULL : (struct sockaddr *)sa.data),
            sa.size);

    if (n < 0)
        return error_tuple(env, errno);

    return enif_make_tuple2(env, atom_ok, enif_make_int64(env, n));
}
Exemple #6
0
static ERL_NIF_TERM
list_to_cstr(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
  int err, written, tmp;
  unsigned int l;
  char* cstr;

  err = enif_get_list_length(env, argv[0], &l);
  if (!err) {
    goto error;
  }
  l+=1; // Null Termination
  cstr = enif_alloc(sizeof(char)*l);
  if (!cstr) {
    goto error;
  }
  written = 0;
  while (written<(l)) {
    tmp = enif_get_string(env, argv[0], cstr+written, l-written, ERL_NIF_LATIN1);
    if (tmp<=0) {
      enif_free(cstr);
      goto error;
    }
    written += tmp;
  }

  return enif_make_tuple2(env,
			  enif_make_int64(env, (ptr_t)cstr),
			  enif_make_string(env, "nifty.char *", ERL_NIF_LATIN1));

 error:
  return enif_make_badarg(env);
}
/*-----------------------------------------------------------------------------------------------------------------------*/
static ERL_NIF_TERM get_int64_field(ErlNifEnv* env, int32_t argc, ERL_NIF_TERM const argv[])
{
   ERL_NIF_TERM parser_res;
   ERL_NIF_TERM msg_res;
   ERL_NIF_TERM group_res;
   ParserRes* parser = NULL;
   FIXMsg* msg = NULL;
   FIXGroup* group = NULL;
   ERL_NIF_TERM res = get_parser_msg_group(env, argv[0], &parser_res, &msg_res, &group_res, &parser, &msg, &group);
   if (res != ok_atom)
   {
      return res;
   }
   int32_t tagNum = 0;
   if (!enif_get_int(env, argv[1], &tagNum))
   {
      return make_error(env, FIX_FAILED, "Wrong tag num.");
   }
   int64_t val = 0;
   FIXError* error = NULL;
   pthread_rwlock_rdlock(&parser->lock);
   FIXErrCode err = fix_msg_get_int64(msg, group, tagNum, &val, &error);
   pthread_rwlock_unlock(&parser->lock);
   if (err == FIX_FAILED)
   {
      ERL_NIF_TERM ret = make_parser_error(env, fix_error_get_code(error), fix_error_get_text(error));
      fix_error_free(error);
      return ret;
   }
   return enif_make_tuple2(env, ok_atom, enif_make_int64(env, val));
}
ERL_NIF_TERM _hh_lowest_at(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
    int64_t value = 0;
    hh_ctx_t* ctx = NULL;

    ErlNifResourceType* ctx_type = get_hh_ctx_type(env);
    if (argc != 2 ||
        ctx_type == NULL ||
        !enif_get_resource(env, argv[0], ctx_type, (void **)&ctx) ||
        ctx->data == NULL ||
        !enif_get_int64(env, argv[1], &value))
    {
        return enif_make_badarg(env);
    }
   
    if (ctx != NULL)
    {
        return enif_make_int64(
            env,
            hdr_lowest_equivalent_value(ctx->data, value)
        );
    }

    return make_error(env, "bad_hdr_histogram_nif_impl");
}
Exemple #9
0
static ERL_NIF_TERM pwrite_nif_impl(efile_data_t *d, ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) {
    ErlNifIOVec vec, *input = &vec;
    Sint64 bytes_written, offset;
    ERL_NIF_TERM tail;

    if(argc != 2 || !enif_is_number(env, argv[0])
                 || !enif_inspect_iovec(env, 64, argv[1], &tail, &input)) {
        return enif_make_badarg(env);
    }

    if(!enif_get_int64(env, argv[0], &offset) || offset < 0) {
        return posix_error_to_tuple(env, EINVAL);
    }

    bytes_written = efile_pwritev(d, offset, input->iov, input->iovcnt);

    if(bytes_written < 0) {
        return posix_error_to_tuple(env, d->posix_errno);
    }

    if(!enif_is_empty_list(env, tail)) {
        ASSERT(bytes_written > 0);
        return enif_make_tuple3(env, am_continue,
            enif_make_int64(env, bytes_written), tail);
    }

    return am_ok;
}
Exemple #10
0
/**
 * Erlang Wrapper for geonum_encode
 */
ERL_NIF_TERM
erl_geonum_encode(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
    double lat;
    double lon;
    int precision;
    long long bin_geonum[1];

    if(!enif_get_double(env, argv[0], &lat)) {
        return enif_make_badarg(env);
    }

    if(!enif_get_double(env, argv[1], &lon)) {
        return enif_make_badarg(env);
    }

    if(!enif_get_int(env, argv[2], &precision)) {
        return enif_make_badarg(env);
    }

    if(precision >= GEONUM_MAX || precision < 1) {
        return make_error(env, "precision_range");
    }

    geonum_encode(lat, lon, precision, bin_geonum);

    return make_ok(env, enif_make_int64(env, bin_geonum[0]));
}
Exemple #11
0
static enum CXChildVisitResult
visitor_enum_cb(CXCursor cursor, CXCursor parent, CXClientData client_data) {
  EnumData* data = (EnumData*)client_data;
  ErlNifEnv *env = data->env;
  ERL_NIF_TERM name;
  ERL_NIF_TERM value;
  long long cvalue;

  CXString tmp;
  char* cstr;

  switch (clang_getCursorKind(cursor)) {
    case CXCursor_EnumConstantDecl: {
      tmp = clang_getCursorSpelling(cursor);
      cstr = (char*)clang_getCString(tmp);
      cvalue = clang_getEnumConstantDeclValue(cursor);
      name = enif_make_string(env, cstr, ERL_NIF_LATIN1);
      value = enif_make_int64(env, cvalue);
      data->enum_values = enif_make_list_cell(env,
                                              enif_make_tuple2(env, name, value),
                                              data->enum_values);
    }
    default: {
      return CXChildVisit_Continue;
    }
  }
}
Exemple #12
0
void
update_callback(void *arg, int sqlite_operation_type, char const *sqlite_database, char const *sqlite_table, sqlite3_int64 sqlite_rowid)
{
    esqlite_connection *db = (esqlite_connection *)arg;
    esqlite_command *cmd = NULL;
    ERL_NIF_TERM type, table, rowid;
    cmd = command_create();

    if(db == NULL)
        return;

    if(!cmd)
	    return;

    rowid = enif_make_int64(cmd->env, sqlite_rowid);
    table = enif_make_string(cmd->env, sqlite_table, ERL_NIF_LATIN1);

    switch(sqlite_operation_type) {
        case SQLITE_INSERT:
            type = make_atom(cmd->env, "insert");
            break;
        case SQLITE_DELETE:
            type = make_atom(cmd->env, "delete");
            break;
        case SQLITE_UPDATE:
            type = make_atom(cmd->env, "update");
            break;
        default:
            return;
    }
    cmd->type = cmd_notification;
    cmd->arg = enif_make_tuple3(cmd->env, type, table, rowid);
    push_command(cmd->env, db, cmd);
}
Exemple #13
0
/*
 * Nr of changes
 */
static ERL_NIF_TERM
do_changes(ErlNifEnv *env, esqlite_connection *conn, const ERL_NIF_TERM arg)
{
    int changes = sqlite3_changes(conn->db);

    ERL_NIF_TERM changes_term = enif_make_int64(env, changes);
    return make_ok_tuple(env, changes_term);
}
Exemple #14
0
static bool
decode_visit_int64(const bson_iter_t *iter,
                   const char        *key,
                   int64_t            v_int64,
                   void              *data)
{
    decode_state *ds = data;
    ERL_NIF_TERM  out = enif_make_int64(ds->env, v_int64);
    vec_push(ds->vec, out);
    return false;
}
Exemple #15
0
static int test_int64(ErlNifEnv* env, ErlNifSInt64 i1)
{
    ErlNifSInt64 i2 = 0;
    ERL_NIF_TERM int_term = enif_make_int64(env, i1);
    if (!enif_get_int64(env,int_term, &i2) || i1 != i2) {
	fprintf(stderr, "test_int64(%ld) ...FAILED i2=%ld\r\n",
		(long)i1, (long)i2);
	return 0;
    }
    return 1;
}
Exemple #16
0
static bool
decode_visit_date_time(const bson_iter_t *iter,
                       const char        *key,
                       int64_t            msec_since_epoch,
                       void              *data)
{
    decode_state *ds = data;
    ERL_NIF_TERM  out = enif_make_int64(ds->env, msec_since_epoch);
    out = enif_make_tuple2(ds->env, ds->st->atom_s_date, out);
    vec_push(ds->vec, out);
    return false;
}
Exemple #17
0
ERL_NIF_TERM get_counter_value(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) {
    mzc_ctx_t* ctx = NULL;

    ErlNifResourceType* ctx_type = get_mzc_ctx_type(env);
    if (argc != 1 ||
        !enif_get_resource(env, argv[0], ctx_type, (void **)&ctx))
    {
        return enif_make_badarg(env);
    }

    return enif_make_int64(env, atomic_wide_get(&ctx->value));
}
Exemple #18
0
static ERL_NIF_TERM
raw_deref(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
  int err;
  ptr_t ptr;
  err = nifty_get_ptr(env, argv[0], &ptr);
  if (!err) {
    goto error;
  }
  return enif_make_int64(env, (*(ptr_t*)ptr));
 error:
  return enif_make_badarg(env);
}
Exemple #19
0
/**
 * Erlang Wrapper for  geonum_neighbor
 */
ERL_NIF_TERM
erl_geonum_neighbor(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
    long long bin_neighbor[1];
    long long geonum;
    char dir[2];

    int dir_val;
    unsigned int dir_len;

    if(!enif_get_int64(env, argv[0], &geonum)) {
        return enif_make_badarg(env);
    }

    if(!enif_get_atom_length(env, argv[1], &dir_len, ERL_NIF_LATIN1))
    {
        return enif_make_badarg(env);
    }

    if(dir_len > sizeof(dir)) {
        return enif_make_badarg(env);
    }

    if(!enif_get_atom(env, argv[1], dir, sizeof(dir), ERL_NIF_LATIN1))
    {
        return enif_make_badarg(env);
    }

    switch (dir[0]) {
        case 'w':
            dir_val = 0;
            break;
        case 'e':
            dir_val = 1;
            break;
        case 'n':
            dir_val = 2;
            break;
        case 's':
            dir_val = 3;
            break;
        default:
            return enif_make_badarg(env);
    }


    geonum_neighbor(geonum, dir_val, bin_neighbor);

    return make_ok(env, enif_make_int64(env, bin_neighbor[0]));
}
Exemple #20
0
static ERL_NIF_TERM elibart_size(ErlNifEnv* env, int argc,
                                          const ERL_NIF_TERM argv[])
{
    art_tree* t;

    // extract arguments atr_tree
    if (argc != 1)
        return enif_make_badarg(env);
    if(!enif_get_resource(env, argv[0], elibart_RESOURCE, (void**) &t))
        return enif_make_badarg(env);

    uint64_t size = art_size(t);

    return enif_make_int64(env, size);
}
Exemple #21
0
/*
* insert action
*/
static ERL_NIF_TERM
do_insert(ErlNifEnv *env, esqlite_connection *conn, const ERL_NIF_TERM arg)
{
    ErlNifBinary bin;
    int rc;
    ERL_NIF_TERM eos = enif_make_int(env, 0);

    enif_inspect_iolist_as_binary(env,
        enif_make_list2(env, arg, eos), &bin);

    rc = sqlite3_exec(conn->db, (char *) bin.data, NULL, NULL, NULL);
    if(rc != SQLITE_OK)
        return make_sqlite3_error_tuple(env, rc, conn->db);
    sqlite3_int64 last_rowid = sqlite3_last_insert_rowid(conn->db);
    ERL_NIF_TERM last_rowid_term = enif_make_int64(env, last_rowid);
    return make_ok_tuple(env, last_rowid_term);
}
static void*
thr_main(void* obj)
{
    state_t* state = (state_t*) obj;
    ErlNifEnv* env = enif_alloc_env();
    ErlNifPid* pid;
    ERL_NIF_TERM msg;

    while((pid = queue_pop(state->queue)) != NULL)
    {
        msg = enif_make_int64(env, random());
        enif_send(NULL, pid, env, msg);
        enif_free(pid);
        enif_clear_env(env);
    }

    return NULL;
}
Exemple #23
0
/* 0: fd, 1: list of buffers */
    static ERL_NIF_TERM
nif_writev(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
{
    ERL_NIF_TERM head = {0};
    ERL_NIF_TERM tail = {0};
    struct iovec iovs[IOVMAX];
    int fd = -1;
    unsigned iovcnt;
    ssize_t n = 0;

    if (!enif_get_int(env, argv[0], &fd))
        return enif_make_badarg(env);

    tail = argv[1];

    if (!enif_get_list_length(env, tail, &iovcnt))
        return enif_make_badarg(env);

    if (!iovcnt || iovcnt > IOVMAX)
        return enif_make_badarg(env);

    iovcnt = 0;

    while (enif_get_list_cell(env, tail, &head, &tail)) {
        struct iovec *iov = &iovs[iovcnt++];
        ErlNifBinary buf = {0};

        if (!enif_inspect_binary(env, head, &buf))
            return enif_make_badarg(env);

        iov->iov_base = buf.data;
        iov->iov_len = buf.size;
    }

    n = writev(fd, iovs, iovcnt);

    if (n < 0)
        return error_tuple(env, errno);

    return enif_make_tuple2(env, atom_ok, enif_make_int64(env, n));
}
Exemple #24
0
/* 0: fd, 1: buffer */
    static ERL_NIF_TERM
nif_write(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
{
    int fd = -1;
    ssize_t n = 0;

    ErlNifBinary buf = {0};

    if (!enif_get_int(env, argv[0], &fd))
        return enif_make_badarg(env);

    if (!enif_inspect_binary(env, argv[1], &buf))
        return enif_make_badarg(env);

    n = write(fd, buf.data, buf.size);

    if (n < 0)
        return error_tuple(env, errno);

    return enif_make_tuple2(env, atom_ok, enif_make_int64(env, n));
}
Exemple #25
0
    static ERL_NIF_TERM
nif_write(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
{
    SRLY_STATE *sp = NULL;
    ErlNifBinary buf = {0};
    ssize_t n = -1;


    if (!enif_get_resource(env, argv[0], SRLY_STATE_RESOURCE, (void **)&sp))
        return enif_make_badarg(env);

    if (!enif_inspect_iolist_as_binary(env, argv[1], (ErlNifBinary *)&buf))
        return enif_make_badarg(env);

    n = write(sp->fd, buf.data, buf.size);

    if (n < 0)
        return error_tuple(env, errno);

    return enif_make_tuple2(env, atom_ok, enif_make_int64(env, n));
}
Exemple #26
0
/**
 * Erlang Wrapper for binary geonum_neighbor
 */
ERL_NIF_TERM
erl_geonum_all_neighbors(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
    long long neighbors[8];
    long long geonum;

    if(!enif_get_int64(env, argv[0], &geonum)) {
        return enif_make_badarg(env);
    }

    geonum_all_neighbors(geonum, neighbors);

    return make_ok(env, enif_make_list8(env,
    		enif_make_int64(env, neighbors[0]),
    		enif_make_int64(env, neighbors[1]),
    		enif_make_int64(env, neighbors[2]),
    		enif_make_int64(env, neighbors[3]),
    		enif_make_int64(env, neighbors[4]),
    		enif_make_int64(env, neighbors[5]),
    		enif_make_int64(env, neighbors[6]),
    		enif_make_int64(env, neighbors[7])
    ));
}
Exemple #27
0
/*-----------------------------------------------------------------------------------------------------------------------*/
static ERL_NIF_TERM get_header(ErlNifEnv* env, int32_t argc, ERL_NIF_TERM const argv[])
{
   int32_t delimiter = 0;
   ErlNifBinary bin;
   if (!enif_inspect_binary(env, argv[0], &bin))
   {
      return make_error(env, FIX_FAILED, "Wrong delimiter.");
   }
   if (!enif_get_int(env, argv[1], &delimiter) || delimiter <= 0 || delimiter >= 255)
   {
      return make_error(env, FIX_FAILED, "Wrong binary.");
   }
   char const* beginString = NULL;
   uint32_t beginStringLen = 0;
   char const* msgType = NULL;
   uint32_t msgTypeLen = 0;
   char const* senderCompID = NULL;
   uint32_t senderCompIDLen = 0;
   char const* targetCompID = NULL;
   uint32_t targetCompIDLen = 0;
   int64_t msgSeqNum = 0;
   FIXError* error = NULL;
   if (FIX_FAILED == fix_parser_get_header((char const*)bin.data, bin.size, delimiter,
         &beginString, &beginStringLen, &msgType, &msgTypeLen, &senderCompID, &senderCompIDLen,
         &targetCompID, &targetCompIDLen, &msgSeqNum, &error))
   {
      ERL_NIF_TERM err = make_error(env, fix_error_get_code(error), fix_error_get_text(error));
      fix_error_free(error);
      return err;
   }
   return enif_make_tuple2(env, ok_atom,
            enif_make_tuple6(env, msg_header,
               enif_make_string_len(env, beginString, beginStringLen, ERL_NIF_LATIN1),
               enif_make_string_len(env, msgType, msgTypeLen, ERL_NIF_LATIN1),
               enif_make_string_len(env, senderCompID, senderCompIDLen, ERL_NIF_LATIN1),
               enif_make_string_len(env, targetCompID, targetCompIDLen, ERL_NIF_LATIN1),
               enif_make_int64(env, msgSeqNum)));
}
ERL_NIF_TERM _hh_add(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
    hh_ctx_t* ctx = NULL;
    hh_ctx_t* from = NULL;

    ErlNifResourceType* ctx_type = get_hh_ctx_type(env);
    if (argc != 2 ||
        ctx_type == NULL ||
        !enif_get_resource(env, argv[0], ctx_type, (void **)&ctx) ||
        ctx->data == NULL ||
        !enif_get_resource(env, argv[1], ctx_type, (void **)&from) ||
        from->data == NULL)
    {
        return enif_make_badarg(env);
    }
   
    if (ctx != NULL)
    {
        return enif_make_int64(env, hdr_add(ctx->data, from->data));
    }

    return make_error(env, "bad_hdr_histogram_nif_impl");
}
Exemple #29
0
static ERL_NIF_TERM
make_cell(ErlNifEnv *env, sqlite3_stmt *statement, unsigned int i)
{
    int type = sqlite3_column_type(statement, i);
     
    switch(type) {
    case SQLITE_INTEGER:
	    return enif_make_int64(env, sqlite3_column_int64(statement, i));
    case SQLITE_FLOAT:
	    return enif_make_double(env, sqlite3_column_double(statement, i));
    case SQLITE_BLOB:
        return enif_make_tuple2(env, make_atom(env, "blob"), 
            make_binary(env, sqlite3_column_blob(statement, i), 
                sqlite3_column_bytes(statement, i)));
    case SQLITE_NULL:
	    return make_atom(env, "undefined");
    case SQLITE_TEXT:
	    return make_binary(env, sqlite3_column_text(statement, i), 
            sqlite3_column_bytes(statement, i));
    default:
	    return make_atom(env, "should_not_happen");
    }
}
ERL_NIF_TERM _hi_next(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
    hi_ctx_t* ctx = NULL;

    ErlNifResourceType* ctx_type = get_hi_ctx_type(env);
    if (argc != 1 ||
        ctx_type == NULL ||
        !enif_get_resource(env, argv[0], ctx_type, (void **)&ctx))
    {
        return enif_make_badarg(env);
    }

    if (ctx != NULL && ctx->type == HDR_ITER_REC)
    {
        // skip until first non-zero index
        bool has_next = false;
        while (ctx->iter != NULL && (has_next = hdr_recorded_iter_next(ctx->iter)))
        {
            struct hdr_recorded_iter* x = ((struct hdr_recorded_iter*)ctx->iter);
            struct hdr_iter iter = x->iter;
            if (0 != iter.count_at_index)
            {
                int64_t stp = x->count_added_in_this_iteration_step;
                int32_t bdx = iter.bucket_index;
                int64_t sdx = iter.sub_bucket_index;
                int64_t val = iter.value_from_index;
                int64_t cat = iter.count_at_index;
                int64_t cto = iter.count_to_index;
                int64_t heq = iter.highest_equivalent_value;
                return enif_make_tuple2(env,
                  ATOM_RECORD,
                  enif_make_list(env, 7,
                      enif_make_tuple2(env,
                          ATOM_BUCKET_IDX,
                          enif_make_int(env,bdx)),
                      enif_make_tuple2(env,
                          ATOM_SUB_BUCKET_IDX,
                          enif_make_int64(env,sdx)),
                      enif_make_tuple2(env,
                          ATOM_VAL_FROM_IDX,
                          enif_make_int64(env,val)),
                      enif_make_tuple2(env,
                          ATOM_VAL_AT_IDX,
                          enif_make_int64(env,cat)),
                      enif_make_tuple2(env,
                          ATOM_COUNT_AT_IDX,
                          enif_make_int64(env,cto)),
                      enif_make_tuple2(env,
                          ATOM_HIGHEST_EQUIV_VAL,
                          enif_make_int64(env,heq)),
                      enif_make_tuple2(env,
                          ATOM_STEP_COUNT,
                          enif_make_int64(env,stp))));
            }
        }
    }

    if (ctx != NULL && ctx->type == HDR_ITER_LIN)
    {
        // skip until first non-zero index
        bool has_next = false;
        while (ctx->iter != NULL && (has_next = hdr_linear_iter_next(ctx->iter)))
        {
            struct hdr_linear_iter* x = ((struct hdr_linear_iter*)ctx->iter);
            struct hdr_iter iter = x->iter;
            if (0 != iter.count_at_index)
            {
                int64_t stp = x->count_added_in_this_iteration_step;
                int32_t vub = x->value_units_per_bucket;
                int64_t nvl = x->next_value_reporting_level;
                int64_t nve = x->next_value_reporting_level_lowest_equivalent;
                int32_t bdx = iter.bucket_index;
                int64_t sdx = iter.sub_bucket_index;
                int64_t val = iter.value_from_index;
                int64_t cat = iter.count_at_index;
                int64_t cto = iter.count_to_index;
                int64_t heq = iter.highest_equivalent_value;
                return enif_make_tuple2(env,
                  ATOM_LINEAR,
                  enif_make_list(env, 10,
                      enif_make_tuple2(env,
                          ATOM_BUCKET_IDX,
                          enif_make_int(env,bdx)),
                      enif_make_tuple2(env,
                          ATOM_SUB_BUCKET_IDX,
                          enif_make_int64(env,sdx)),
                      enif_make_tuple2(env,
                          ATOM_VAL_FROM_IDX,
                          enif_make_int64(env,val)),
                      enif_make_tuple2(env,
                          ATOM_VAL_AT_IDX,
                          enif_make_int64(env,cat)),
                      enif_make_tuple2(env,
                          ATOM_COUNT_AT_IDX,
                          enif_make_int64(env,cto)),
                      enif_make_tuple2(env,
                          ATOM_HIGHEST_EQUIV_VAL,
                          enif_make_int64(env,heq)),
                      enif_make_tuple2(env,
                          ATOM_VAL_UNITS_PER_BUCKET,
                          enif_make_int(env,vub)),
                      enif_make_tuple2(env,
                          ATOM_STEP_COUNT,
                          enif_make_int64(env,stp)),
                      enif_make_tuple2(env,
                          ATOM_NEXT_VAL_REP_LVL,
                          enif_make_int64(env,nvl)),
                      enif_make_tuple2(env,
                          ATOM_NEXT_VAL_REP_LVL_LOW_EQUIV,
                          enif_make_int64(env,nve))));
            }
        }
    }

    if (ctx != NULL && ctx->type == HDR_ITER_LOG)
    {
        // skip until first non-zero index
        bool has_next = false;
        while (ctx->iter != NULL && (has_next = hdr_log_iter_next(ctx->iter)))
        {
            struct hdr_log_iter* x = (struct hdr_log_iter*)ctx->iter;
            struct hdr_iter iter = x->iter;
            if (0 != iter.count_at_index)
            {
                int64_t stp = x->count_added_in_this_iteration_step;
                int32_t vfb = x->value_units_first_bucket;
                double lgb = x->log_base;
                int64_t nvl = x->next_value_reporting_level;
                int64_t nve = x->next_value_reporting_level_lowest_equivalent;
                int32_t bdx = iter.bucket_index;
                int64_t sdx = iter.sub_bucket_index;
                int64_t val = iter.value_from_index;
                int64_t cat = iter.count_at_index;
                int64_t cto = iter.count_to_index;
                int64_t heq = iter.highest_equivalent_value;
                return enif_make_tuple2(env,
                  ATOM_LOGARITHMIC,
                  enif_make_list(env, 11,
                      enif_make_tuple2(env,
                          ATOM_BUCKET_IDX,
                          enif_make_int(env,bdx)),
                      enif_make_tuple2(env,
                          ATOM_SUB_BUCKET_IDX,
                          enif_make_int64(env,sdx)),
                      enif_make_tuple2(env,
                          ATOM_VAL_FROM_IDX,
                          enif_make_int64(env,val)),
                      enif_make_tuple2(env,
                          ATOM_VAL_AT_IDX,
                          enif_make_int64(env,cat)),
                      enif_make_tuple2(env,
                          ATOM_COUNT_AT_IDX,
                          enif_make_int64(env,cto)),
                      enif_make_tuple2(env,
                          ATOM_HIGHEST_EQUIV_VAL,
                          enif_make_int64(env,heq)),
                      enif_make_tuple2(env,
                          ATOM_VAL_UNITS_FIRST_BUCKET,
                          enif_make_int(env,vfb)),
                      enif_make_tuple2(env,
                          ATOM_STEP_COUNT,
                          enif_make_int64(env,stp)),
                      enif_make_tuple2(env,
                          ATOM_LOG_BASE,
                          enif_make_double(env,lgb)),
                      enif_make_tuple2(env,
                          ATOM_NEXT_VAL_REP_LVL,
                          enif_make_int64(env,nvl)),
                      enif_make_tuple2(env,
                          ATOM_NEXT_VAL_REP_LVL_LOW_EQUIV,
                          enif_make_int64(env,nve))));
            }
        }
    }

    if (ctx != NULL && ctx->type == HDR_ITER_PCT)
    {
        // skip until first non-zero index
        bool has_next = false;
        while (ctx->iter != NULL && (has_next = hdr_percentile_iter_next(ctx->iter)))
        {
            struct hdr_percentile_iter* x = (struct hdr_percentile_iter*)ctx->iter;
            struct hdr_iter iter = x->iter;
            if (0 != iter.count_at_index)
            {
                bool slv = x->seen_last_value;
                int32_t tph = x->ticks_per_half_distance;
                double pti = x->percentile_to_iterate_to;
                double pct = x->percentile;
                int32_t bdx = iter.bucket_index;
                int64_t sdx = iter.sub_bucket_index;
                int64_t val = iter.value_from_index;
                int64_t cat = iter.count_at_index;
                int64_t cto = iter.count_to_index;
                int64_t heq = iter.highest_equivalent_value;
                return enif_make_tuple2(env,
                  ATOM_PERCENTILE,
                  enif_make_list(env, 10,
                      enif_make_tuple2(env,
                          ATOM_BUCKET_IDX,
                          enif_make_int(env,bdx)),
                      enif_make_tuple2(env,
                          ATOM_SUB_BUCKET_IDX,
                          enif_make_int64(env,sdx)),
                      enif_make_tuple2(env,
                          ATOM_VAL_FROM_IDX,
                          enif_make_int64(env,val)),
                      enif_make_tuple2(env,
                          ATOM_VAL_AT_IDX,
                          enif_make_int64(env,cat)),
                      enif_make_tuple2(env,
                          ATOM_COUNT_AT_IDX,
                          enif_make_int64(env,cto)),
                      enif_make_tuple2(env,
                          ATOM_HIGHEST_EQUIV_VAL,
                          enif_make_int64(env,heq)),
                      enif_make_tuple2(env,
                          ATOM_SEEN_LAST_VAL,
                          enif_make_atom(env,slv ? "true" : "false")),
                      enif_make_tuple2(env,
                          ATOM_PERCENTILE_TO_ITERATE_TO,
                          enif_make_double(env,pti)),
                      enif_make_tuple2(env,
                          ATOM_PERCENTILE,
                          enif_make_double(env,pct)),
                      enif_make_tuple2(env,
                          ATOM_TICKS_PER_HALF_DISTANCE,
                          enif_make_int(env,tph))));
            }
        }
    }

    return enif_make_tuple2(
        env,
        ATOM_FALSE,
        enif_make_tuple(env,0)
    );
}