Current section

Files

Jump to
bunch_native c_src bunch bunch.c
Raw

c_src/bunch/bunch.c

#include "bunch.h"
static const char * errno_to_string(int num);
/**
* Builds `{:error, reason}`.
*/
ERL_NIF_TERM bunch_make_error(ErlNifEnv* env, ERL_NIF_TERM reason) {
ERL_NIF_TERM tuple[2] = {
enif_make_atom(env, "error"),
reason
};
return enif_make_tuple_from_array(env, tuple, 2);
}
/**
* Builds `{:ok, arg}`.
*/
ERL_NIF_TERM bunch_make_ok_tuple(ErlNifEnv* env, ERL_NIF_TERM arg) {
ERL_NIF_TERM tuple[2] = {
enif_make_atom(env, "ok"),
arg
};
return enif_make_tuple_from_array(env, tuple, 2);
}
/**
* Builds `{:ok, arg1, arg2}`.
*/
ERL_NIF_TERM bunch_make_ok_tuple2(ErlNifEnv* env, ERL_NIF_TERM arg1, ERL_NIF_TERM arg2) {
ERL_NIF_TERM tuple[3] = {
enif_make_atom(env, "ok"),
arg1,
arg2
};
return enif_make_tuple_from_array(env, tuple, 3);
}
/**
* Builds `:ok`.
*/
ERL_NIF_TERM bunch_make_ok(ErlNifEnv* env) {
return enif_make_atom(env, "ok");
}
/**
* Builds `:todo`.
*/
ERL_NIF_TERM bunch_make_todo(ErlNifEnv* env) {
return enif_make_atom(env, "todo");
}
/**
* Builds `{:error, {:args, field, description}}` for returning when
* certain constructor-style functions get invalid arguments.
*/
ERL_NIF_TERM bunch_make_error_args(ErlNifEnv* env, const char* field, const char *description) {
ERL_NIF_TERM tuple[3] = {
enif_make_atom(env, "args"),
enif_make_atom(env, field),
enif_make_string(env, description, ERL_NIF_LATIN1)
};
return bunch_make_error(env, enif_make_tuple_from_array(env, tuple, 3));
}
/**
* Helper for returning errors from system calls using errno.
* Builds `{:error, {errno_atom, fun_called_atom}}` where errno_atom
* is lowercase version of POSIX error name and fun_called_atom is the name
* of the function that returned error
*/
ERL_NIF_TERM bunch_make_error_errno(ErlNifEnv* env, const char* call) {
ERL_NIF_TERM tuple[2] = {
enif_make_atom(env, errno_to_string(errno)),
enif_make_atom(env, call)
};
return bunch_make_error(env, enif_make_tuple_from_array(env, tuple, 2));
}
/**
* Builds `{:error, {:internal, reason}}` for returning when certain
* constructor-style functions fails on internal stuff that should generally
* speaking, not fail.
*/
ERL_NIF_TERM bunch_make_error_internal(ErlNifEnv* env, const char* reason) {
ERL_NIF_TERM tuple[3] = {
enif_make_atom(env, "internal"),
enif_make_atom(env, reason)
};
return bunch_make_error(env, enif_make_tuple_from_array(env, tuple, 2));
}
static const char * errno_to_string(int num) {
switch (num) {
#ifdef E2BIG
case E2BIG:
return "e2big";
#endif
#ifdef EACCES
case EACCES:
return "eacces";
#endif
#ifdef EADDRINUSE
case EADDRINUSE:
return "eaddrinuse";
#endif
#ifdef EADDRNOTAVAIL
case EADDRNOTAVAIL:
return "eaddrnotavail";
#endif
#ifdef EAFNOSUPPORT
case EAFNOSUPPORT:
return "eafnosupport";
#endif
#ifdef EAGAIN
case EAGAIN:
return "eagain";
#endif
#ifdef EALREADY
case EALREADY:
return "ealready";
#endif
#ifdef EBADE
case EBADE:
return "ebade";
#endif
#ifdef EBADF
case EBADF:
return "ebadf";
#endif
#ifdef EBADFD
case EBADFD:
return "ebadfd";
#endif
#ifdef EBADMSG
case EBADMSG:
return "ebadmsg";
#endif
#ifdef EBADR
case EBADR:
return "ebadr";
#endif
#ifdef EBADRQC
case EBADRQC:
return "ebadrqc";
#endif
#ifdef EBADSLT
case EBADSLT:
return "ebadslt";
#endif
#ifdef EBUSY
case EBUSY:
return "ebusy";
#endif
#ifdef ECANCELED
case ECANCELED:
return "ecanceled";
#endif
#ifdef ECHILD
case ECHILD:
return "echild";
#endif
#ifdef ECHRNG
case ECHRNG:
return "echrng";
#endif
#ifdef ECOMM
case ECOMM:
return "ecomm";
#endif
#ifdef ECONNABORTED
case ECONNABORTED:
return "econnaborted";
#endif
#ifdef ECONNREFUSED
case ECONNREFUSED:
return "econnrefused";
#endif
#ifdef ECONNRESET
case ECONNRESET:
return "econnreset";
#endif
#if defined(EDEADLK) && (!defined(EWOULDBLOCK) || (EDEADLK != EWOULDBLOCK))
case EDEADLK:
return "edeadlk";
#endif
#if defined(EDEADLOCK) && (!defined(EDEADLK) || (EDEADLOCK != EDEADLK))
case EDEADLOCK:
return "edeadlock";
#endif
#ifdef EDESTADDRREQ
case EDESTADDRREQ:
return "edestaddrreq";
#endif
#ifdef EDOM
case EDOM:
return "edom";
#endif
#ifdef EDQUOT
case EDQUOT:
return "edquot";
#endif
#ifdef EEXIST
case EEXIST:
return "eexist";
#endif
#ifdef EFAULT
case EFAULT:
return "efault";
#endif
#ifdef EFBIG
case EFBIG:
return "efbig";
#endif
#ifdef EHOSTDOWN
case EHOSTDOWN:
return "ehostdown";
#endif
#ifdef EHOSTUNREACH
case EHOSTUNREACH:
return "ehostunreach";
#endif
#ifdef EHWPOISON
case EHWPOISON:
return "ehwpoison";
#endif
#ifdef EIDRM
case EIDRM:
return "eidrm";
#endif
#ifdef EILSEQ
case EILSEQ:
return "eilseq";
#endif
#ifdef EINPROGRESS
case EINPROGRESS:
return "einprogress";
#endif
#ifdef EINTR
case EINTR:
return "eintr";
#endif
#ifdef EINVAL
case EINVAL:
return "einval";
#endif
#ifdef EIO
case EIO:
return "eio";
#endif
#ifdef EISCONN
case EISCONN:
return "eisconn";
#endif
#ifdef EISDIR
case EISDIR:
return "eisdir";
#endif
#ifdef EISNAM
case EISNAM:
return "eisnam";
#endif
#ifdef EKEYEXPIRED
case EKEYEXPIRED:
return "ekeyexpired";
#endif
#ifdef EKEYREJECTED
case EKEYREJECTED:
return "ekeyrejected";
#endif
#ifdef EKEYREVOKED
case EKEYREVOKED:
return "ekeyrevoked";
#endif
#ifdef EL2HLT
case EL2HLT:
return "el2hlt";
#endif
#ifdef EL2NSYNC
case EL2NSYNC:
return "el2nsync";
#endif
#ifdef EL3HLT
case EL3HLT:
return "el3hlt";
#endif
#ifdef EL3RST
case EL3RST:
return "el3rst";
#endif
#ifdef ELIBACC
case ELIBACC:
return "elibacc";
#endif
#ifdef ELIBBAD
case ELIBBAD:
return "elibbad";
#endif
#ifdef ELIBMAX
case ELIBMAX:
return "elibmax";
#endif
#ifdef ELIBSCN
case ELIBSCN:
return "elibscn";
#endif
#ifdef ELIBEXEC
case ELIBEXEC:
return "elibexec";
#endif
#ifdef ELNRANGE
case ELNRANGE:
return "elnrange";
#endif
#ifdef ELOOP
case ELOOP:
return "eloop";
#endif
#ifdef EMEDIUMTYPE
case EMEDIUMTYPE:
return "emediumtype";
#endif
#ifdef EMFILE
case EMFILE:
return "emfile";
#endif
#ifdef EMLINK
case EMLINK:
return "emlink";
#endif
#ifdef EMSGSIZE
case EMSGSIZE:
return "emsgsize";
#endif
#ifdef EMULTIHOP
case EMULTIHOP:
return "emultihop";
#endif
#ifdef ENAMETOOLONG
case ENAMETOOLONG:
return "enametoolong";
#endif
#ifdef ENETDOWN
case ENETDOWN:
return "enetdown";
#endif
#ifdef ENETRESET
case ENETRESET:
return "enetreset";
#endif
#ifdef ENETUNREACH
case ENETUNREACH:
return "enetunreach";
#endif
#ifdef ENFILE
case ENFILE:
return "enfile";
#endif
#ifdef ENOANO
case ENOANO:
return "enoano";
#endif
#ifdef ENOBUFS
case ENOBUFS:
return "enobufs";
#endif
#ifdef ENODATA
case ENODATA:
return "enodata";
#endif
#ifdef ENODEV
case ENODEV:
return "enodev";
#endif
#ifdef ENOENT
case ENOENT:
return "enoent";
#endif
#ifdef ENOEXEC
case ENOEXEC:
return "enoexec";
#endif
#ifdef ENOKEY
case ENOKEY:
return "enokey";
#endif
#ifdef ENOLCK
case ENOLCK:
return "enolck";
#endif
#ifdef ENOLINK
case ENOLINK:
return "enolink";
#endif
#ifdef ENOMEDIUM
case ENOMEDIUM:
return "enomedium";
#endif
#ifdef ENOMEM
case ENOMEM:
return "enomem";
#endif
#ifdef ENOMSG
case ENOMSG:
return "enomsg";
#endif
#ifdef ENONET
case ENONET:
return "enonet";
#endif
#ifdef ENOPKG
case ENOPKG:
return "enopkg";
#endif
#ifdef ENOPROTOOPT
case ENOPROTOOPT:
return "enoprotoopt";
#endif
#ifdef ENOSPC
case ENOSPC:
return "enospc";
#endif
#ifdef ENOSR
case ENOSR:
return "enosr";
#endif
#ifdef ENOSTR
case ENOSTR:
return "enostr";
#endif
#ifdef ENOSYS
case ENOSYS:
return "enosys";
#endif
#ifdef ENOTBLK
case ENOTBLK:
return "enotblk";
#endif
#ifdef ENOTCONN
case ENOTCONN:
return "enotconn";
#endif
#ifdef ENOTDIR
case ENOTDIR:
return "enotdir";
#endif
#ifdef ENOTEMPTY
case ENOTEMPTY:
return "enotempty";
#endif
#ifdef ENOTRECOVERABLE
case ENOTRECOVERABLE:
return "enotrecoverable";
#endif
#ifdef ENOTSOCK
case ENOTSOCK:
return "enotsock";
#endif
#ifdef ENOTSUP
case ENOTSUP:
return "enotsup";
#endif
#ifdef ENOTTY
case ENOTTY:
return "enotty";
#endif
#ifdef ENOTUNIQ
case ENOTUNIQ:
return "enotuniq";
#endif
#ifdef ENXIO
case ENXIO:
return "enxio";
#endif
#if defined(EOPNOTSUPP) && (!defined(ENOTSUP) || (EOPNOTSUPP != ENOTSUP))
case EOPNOTSUPP:
return "eopnotsupp";
#endif
#ifdef EOVERFLOW
case EOVERFLOW:
return "eoverflow";
#endif
#ifdef EOWNERDEAD
case EOWNERDEAD:
return "eownerdead";
#endif
#ifdef EPERM
case EPERM:
return "eperm";
#endif
#ifdef EPFNOSUPPORT
case EPFNOSUPPORT:
return "epfnosupport";
#endif
#ifdef EPIPE
case EPIPE:
return "epipe";
#endif
#ifdef EPROTO
case EPROTO:
return "eproto";
#endif
#ifdef EPROTONOSUPPORT
case EPROTONOSUPPORT:
return "eprotonosupport";
#endif
#ifdef EPROTOTYPE
case EPROTOTYPE:
return "eprototype";
#endif
#ifdef ERANGE
case ERANGE:
return "erange";
#endif
#ifdef EREMCHG
case EREMCHG:
return "eremchg";
#endif
#ifdef EREMOTE
case EREMOTE:
return "eremote";
#endif
#ifdef EREMOTEIO
case EREMOTEIO:
return "eremoteio";
#endif
#ifdef ERESTART
case ERESTART:
return "erestart";
#endif
#ifdef ERFKILL
case ERFKILL:
return "erfkill";
#endif
#ifdef EROFS
case EROFS:
return "erofs";
#endif
#ifdef ESHUTDOWN
case ESHUTDOWN:
return "eshutdown";
#endif
#ifdef ESPIPE
case ESPIPE:
return "espipe";
#endif
#ifdef ESOCKTNOSUPPORT
case ESOCKTNOSUPPORT:
return "esocktnosupport";
#endif
#ifdef ESRCH
case ESRCH:
return "esrch";
#endif
#ifdef ESTALE
case ESTALE:
return "estale";
#endif
#ifdef ESTRPIPE
case ESTRPIPE:
return "estrpipe";
#endif
#ifdef ETIME
case ETIME:
return "etime";
#endif
#ifdef ETIMEDOUT
case ETIMEDOUT:
return "etimedout";
#endif
#ifdef ETOOMANYREFS
case ETOOMANYREFS:
return "etoomanyrefs";
#endif
#ifdef ETXTBSY
case ETXTBSY:
return "etxtbsy";
#endif
#ifdef EUCLEAN
case EUCLEAN:
return "euclean";
#endif
#ifdef EUNATCH
case EUNATCH:
return "eunatch";
#endif
#ifdef EUSERS
case EUSERS:
return "eusers";
#endif
#if defined(EWOULDBLOCK) && (!defined(EAGAIN) || (EWOULDBLOCK != EAGAIN))
case EWOULDBLOCK:
return "ewouldblock";
#endif
#ifdef EXDEV
case EXDEV:
return "exdev";
#endif
#ifdef EXFULL
case EXFULL:
return "exfull";
#endif
}
return "unknown";
}