diff --git a/h3client/Makefile b/h3client/Makefile index 129dd39..64b275d 100644 --- a/h3client/Makefile +++ b/h3client/Makefile @@ -5,9 +5,6 @@ OBJ = $(SRC:.c=.o) HDR = $(wildcard h3c_*.h) LIB = libh3client.a PREFIX ?= /usr/local -TEST_SRC = $(wildcard test_*.c) -TEST_OBJ = $(TEST_SRC:.c=.o) -TEST_TARGET = $(basename $(TEST_OBJ)) all: $(LIB) @@ -19,12 +16,12 @@ $(LIB): $(OBJ) %.o: %.c $(HDR) $(CC) $(CFLAGS) -c $< -o $@ -$(TEST_TARGET): %: %.o $(LIB) $(HDR) +test_h3client: %: %.o $(LIB) $(HDR) $(CC) $(CFLAGS) $< -L. -lh3client -lh3result -lnng -llio -llite_pack -lm -o $@ -check: $(TEST_TARGET) +check: test_h3client ./start_daemon.sh data/ross.5.hmm - for test in $(TEST_TARGET); do ./$$test || exit 1; done + ./test_h3client ./stop_daemon.sh data/ross.5.hmm install: $(LIB) $(HDR) @@ -37,7 +34,7 @@ uninstall: .PHONY: all clean check uninstall clean: - rm -f $(OBJ) $(LIB) $(TEST_OBJ) $(TEST_TARGET) *.d + rm -f $(OBJ) $(LIB) test_h3client.o test_h3client *.d rm -f data/ross.5.hmm.h3f rm -f data/ross.5.hmm.h3i rm -f data/ross.5.hmm.h3m diff --git a/h3client/amsg.c b/h3client/amsg.c deleted file mode 100644 index 96ef489..0000000 --- a/h3client/amsg.c +++ /dev/null @@ -1,141 +0,0 @@ -#include "amsg.h" -#include "nng/nng.h" -#include "timeout.h" -#include -#include - -struct amsg -{ - int len; - struct nng_iov iov[8]; - struct nng_aio *upper_aio; - struct nng_aio *lower_aio; - struct nng_stream *s; - void (*submit)(struct nng_stream *, struct nng_aio *); -}; - -static struct amsg *alloc(nng_stream *s, - void (*submit)(nng_stream *, nng_aio *), int len, - struct nng_iov *, void (*callb)(void *), void *arg, - long deadline); -static void destroy(struct amsg *x); -static void start(struct amsg *x); -static void callback(void *arg); - -struct amsg *h3client_asend(struct nng_stream *s, int len, struct nng_iov *iov, - void (*callb)(void *), void *arg, long deadline) -{ - return alloc(s, &nng_stream_send, len, iov, callb, arg, deadline); -} - -struct amsg *h3client_arecv(struct nng_stream *s, size_t len, void *data, - void (*callb)(void *), void *arg, long deadline) -{ - struct nng_iov iov = {.iov_buf = data, .iov_len = len}; - return alloc(s, &nng_stream_recv, 1, &iov, callb, arg, deadline); -} - -void h3client_astart(struct amsg *x) { start(x); } - -void h3client_adel(struct amsg *x) { destroy(x); } - -void h3client_acancel(struct amsg *x) { nng_aio_cancel(x->upper_aio); } - -void h3client_astop(struct amsg *x) { nng_aio_stop(x->upper_aio); } - -int h3client_aresult(struct amsg *x) { return nng_aio_result(x->upper_aio); } - -static int consume(int len, struct nng_iov *iov, size_t amount); - -static struct amsg *alloc(nng_stream *s, - void (*submit)(nng_stream *, nng_aio *), int len, - struct nng_iov *iov, void (*callb)(void *), void *arg, - long deadline) -{ - struct amsg *x; - - if ((x = nng_alloc(sizeof(*x))) == NULL) return NULL; - if (nng_aio_alloc(&x->upper_aio, callb, arg) != 0) - { - destroy(x); - return NULL; - } - if (nng_aio_alloc(&x->lower_aio, &callback, x) != 0) - { - destroy(x); - return NULL; - } - - int duration = h3client_timeout(deadline); - nng_aio_set_timeout(x->upper_aio, duration); - nng_aio_set_timeout(x->lower_aio, duration); - - nng_aio_begin(x->upper_aio); - - x->s = s; - x->len = len; - memcpy(x->iov, iov, len * sizeof(*iov)); - x->submit = submit; - - return x; -} - -static void destroy(struct amsg *x) -{ - if (!x) return; - if (x->lower_aio) - { - nng_aio_free(x->lower_aio); - x->lower_aio = NULL; - } - if (x->upper_aio) - { - nng_aio_free(x->upper_aio); - x->upper_aio = NULL; - } - nng_free(x, sizeof(*x)); -} - -static void start(struct amsg *x) -{ - nng_aio_set_iov(x->lower_aio, x->len, x->iov); - x->submit(x->s, x->lower_aio); -} - -static void callback(void *arg) -{ - struct amsg *x = arg; - int rv; - size_t n; - - rv = nng_aio_result(x->lower_aio); - if (rv != 0) - { - nng_aio_finish(x->upper_aio, rv); - return; - } - n = nng_aio_count(x->lower_aio); - - if (!consume(x->len, x->iov, n)) - { - nng_aio_finish(x->upper_aio, 0); - return; - } - - start(x); -} - -static int consume(int len, struct nng_iov *iov, size_t amount) -{ - int rem = len; - for (int i = 0; i < len; ++i) - { - size_t sz = amount < iov->iov_len ? amount : iov->iov_len; - iov->iov_len -= sz; - iov->iov_buf += sz; - amount -= sz; - rem -= iov->iov_len == 0; - ++iov; - } - return rem; -} diff --git a/h3client/amsg.h b/h3client/amsg.h deleted file mode 100644 index 7c0209e..0000000 --- a/h3client/amsg.h +++ /dev/null @@ -1,20 +0,0 @@ -#ifndef AMSG_H -#define AMSG_H - -#include - -struct amsg; -struct nng_iov; -struct nng_stream; - -struct amsg *h3client_asend(struct nng_stream *, int len, struct nng_iov *, - void (*callb)(void *), void *arg, long deadline); -struct amsg *h3client_arecv(struct nng_stream *, size_t len, void *data, - void (*callb)(void *), void *arg, long deadline); -void h3client_astart(struct amsg *); -void h3client_adel(struct amsg *); -void h3client_acancel(struct amsg *); -void h3client_astop(struct amsg *); -int h3client_aresult(struct amsg *); - -#endif diff --git a/h3client/answer.c b/h3client/answer.c deleted file mode 100644 index ca8b55e..0000000 --- a/h3client/answer.c +++ /dev/null @@ -1,302 +0,0 @@ -#include "answer.h" -#include "copy_string.h" -#include "array_size.h" -#include "buff.h" -#include "defer_return.h" -#include "h3c_errno.h" -#include "h3c_result.h" -#include "h3r_alidisplay.h" -#include "h3r_domain.h" -#include "h3r_hit.h" -#include "h3r_stats.h" -#include "h3r_tophits.h" -#include "hmmd_hmmd.h" -#include "utils.h" -#include -#include - -#define BUFF_SIZE 2048 - -struct answer -{ - struct - { - unsigned char data[HMMD_STATUS_PACK_SIZE]; - struct hmmd_status value; - } status; - - struct buff *buff; - int errnum; - char errstr[1024]; - struct hmmd_stats stats; - struct hmmd_tophits tophits; -}; - -struct answer *h3client_answer_new(void) -{ - struct answer *ans = malloc(sizeof(*ans)); - if (!ans) return 0; - - ans->status.data[0] = '\0'; - h3client_hmmd_status_init(&ans->status.value); - - if (!(ans->buff = h3client_buff_new(BUFF_SIZE))) - { - free(ans); - return 0; - } - - ans->errnum = 0; - memset(ans->errstr, '\0', array_size(ans->errstr)); - h3client_hmmd_stats_init(&ans->stats); - h3client_hmmd_tophits_init(&ans->tophits); - return ans; -} - -void h3client_answer_del(struct answer const *ans) -{ - h3client_buff_del(ans->buff); - h3client_hmmd_stats_cleanup((struct hmmd_stats *)&ans->stats); - h3client_hmmd_tophits_cleanup((struct hmmd_tophits *)&ans->tophits); - free((void *)ans); -} - -unsigned char *h3client_answer_status_data(struct answer *ans) -{ - return ans->status.data; -} - -size_t h3client_answer_status_size(void) { return HMMD_STATUS_PACK_SIZE; } - -struct hmmd_status const *h3client_answer_status_parse(struct answer *ans) -{ - size_t size = 0; - h3client_hmmd_status_parse(&ans->status.value, &size, ans->status.data); - return h3client_answer_status(ans); -} - -struct hmmd_status const *h3client_answer_status(struct answer const *ans) -{ - return &ans->status.value; -} - -int h3client_answer_setup_size(struct answer *ans, size_t size) -{ - ans->buff->size = size; - return h3client_buff_ensure(&ans->buff, size); -} - -unsigned char *h3client_answer_data(struct answer *ans) -{ - return ans->buff->data; -} - -int h3client_answer_parse(struct answer *ans) -{ - int rc = 0; - - unsigned char const *ptr = ans->buff->data; - unsigned char const *end = ptr + ans->buff->size; - if ((rc = h3client_hmmd_stats_parse(&ans->stats, &ptr, end))) goto cleanup; - - rc = h3client_hmmd_tophits_setup(&ans->tophits, &ptr, end, ans->stats.nhits, - ans->stats.nreported, ans->stats.nincluded); - if (rc) goto cleanup; - - if (ptr != end) rc = H3C_EPARSE; - -cleanup: - return rc; -} - -int h3client_answer_parse_error(struct answer *x) -{ - x->errnum = x->status.value.status; - if (x->status.value.msglen >= array_size(x->errstr)) return H3C_ENOMEM; - memcpy(x->errstr, x->buff->data, x->status.value.msglen); - x->errstr[x->status.value.msglen] = '\0'; - return 0; -} - -#define STRXDUP(D, S) (D = h3client_strxdup((D), (S))) - -static int copy_alidisplay(struct h3r_alidisplay *dst, - struct hmmd_alidisplay const *src) -{ - dst->presence = src->presence; - - if (!STRXDUP(dst->rfline, src->rfline)) return H3C_ENOMEM; - if (!STRXDUP(dst->mmline, src->mmline)) return H3C_ENOMEM; - if (!STRXDUP(dst->csline, src->csline)) return H3C_ENOMEM; - if (!STRXDUP(dst->model, src->model)) return H3C_ENOMEM; - if (!STRXDUP(dst->mline, src->mline)) return H3C_ENOMEM; - if (!STRXDUP(dst->aseq, src->aseq)) return H3C_ENOMEM; - if (!STRXDUP(dst->ntseq, src->ntseq)) return H3C_ENOMEM; - if (!STRXDUP(dst->ppline, src->ppline)) return H3C_ENOMEM; - dst->N = src->N; - - if (!STRXDUP(dst->hmmname, src->hmmname)) return H3C_ENOMEM; - if (!STRXDUP(dst->hmmacc, src->hmmacc)) return H3C_ENOMEM; - if (!STRXDUP(dst->hmmdesc, src->hmmdesc)) return H3C_ENOMEM; - dst->hmmfrom = src->hmmfrom; - dst->hmmto = src->hmmto; - dst->M = src->M; - - if (src->sqfrom > UINT32_MAX) return H3C_EOUTRANGE; - if (src->sqto > UINT32_MAX) return H3C_EOUTRANGE; - if (src->L > UINT32_MAX) return H3C_EOUTRANGE; - - if (!STRXDUP(dst->sqname, src->sqname)) return H3C_ENOMEM; - if (!STRXDUP(dst->sqacc, src->sqacc)) return H3C_ENOMEM; - if (!STRXDUP(dst->sqdesc, src->sqdesc)) return H3C_ENOMEM; - dst->sqfrom = src->sqfrom; - dst->sqto = src->sqto; - dst->L = src->L; - - return 0; -} - -static int copy_domain(struct h3r_domain *dst, struct hmmd_domain const *src) -{ - int rc = h3r_domain_setup(dst, src->scores_size); - if (rc) return rc; - - if (src->ienv > UINT32_MAX) defer_return(H3C_EOUTRANGE); - if (src->jenv > UINT32_MAX) defer_return(H3C_EOUTRANGE); - if (src->iali > UINT32_MAX) defer_return(H3C_EOUTRANGE); - if (src->jali > UINT32_MAX) defer_return(H3C_EOUTRANGE); - - dst->ienv = src->ienv; - dst->jenv = src->jenv; - dst->iali = src->iali; - dst->jali = src->jali; - dst->envsc = src->envsc; - dst->domcorrection = src->domcorrection; - dst->dombias = src->dombias; - dst->oasc = src->oasc; - dst->bitscore = src->bitscore; - dst->lnP = src->lnP; - dst->is_reported = src->is_reported; - dst->is_included = src->is_included; - - if (src->scores_size > UINT32_MAX) defer_return(H3C_EOUTRANGE); - for (unsigned i = 0; i < dst->pos_score_size; ++i) - dst->pos_score[i] = src->pos_score[i]; - - if ((rc = copy_alidisplay(&dst->ad, &src->ad))) defer_return(rc); - - return 0; - -defer: - h3r_domain_cleanup(dst); - return rc; -} - -static int copy_hit(struct h3r_hit *dst, struct hmmd_hit const *src) -{ - int rc = h3r_hit_setup(dst, src->ndom); - if (rc) return rc; - - if (!STRXDUP(dst->name, src->name)) defer_return(H3C_ENOMEM); - if (!STRXDUP(dst->acc, src->acc)) defer_return(H3C_ENOMEM); - if (!STRXDUP(dst->desc, src->desc)) defer_return(H3C_ENOMEM); - - dst->sortkey = src->sortkey; - - dst->score = src->score; - dst->pre_score = src->pre_score; - dst->sum_score = src->sum_score; - - dst->lnP = src->lnP; - dst->pre_lnP = src->pre_lnP; - dst->sum_lnP = src->sum_lnP; - - dst->nexpected = src->nexpected; - dst->nregions = src->nregions; - dst->nclustered = src->nclustered; - dst->noverlaps = src->noverlaps; - dst->nenvelopes = src->nenvelopes; - - dst->flags = src->flags; - dst->nreported = src->nreported; - dst->nincluded = src->nincluded; - dst->best_domain = src->best_domain; - - for (unsigned i = 0; i < dst->ndomains; ++i) - { - if ((rc = copy_domain(dst->domains + i, src->dcl + i))) defer_return(rc); - } - - return 0; - -defer: - h3r_hit_cleanup(dst); - return rc; -} - -static int copy_tophits(struct h3r_tophits *dst, struct hmmd_tophits const *src) -{ - int rc = h3r_tophits_setup(dst, src->nhits); - if (rc) return rc; - - dst->nreported = src->nreported; - dst->nincluded = src->nincluded; - dst->is_sorted_by_sortkey = src->is_sorted_by_sortkey; - dst->is_sorted_by_seqidx = src->is_sorted_by_seqidx; - - for (unsigned long i = 0; i < src->nhits; ++i) - { - if ((rc = copy_hit(dst->hits + i, src->hit[i]))) defer_return(rc); - } - - return 0; - -defer: - h3r_tophits_cleanup(dst); - return rc; -} - -static int copy_stats(struct h3r_stats *dst, struct hmmd_stats const *src) -{ - int rc = 0; - - dst->Z = src->Z; - dst->domZ = src->domZ; - - dst->Z_setby = (enum h3r_zsetby)src->Z_setby; - dst->domZ_setby = (enum h3r_zsetby)src->domZ_setby; - - if (src->nmodels > UINT32_MAX) defer_return(H3C_EOUTRANGE); - if (src->nseqs > UINT32_MAX) defer_return(H3C_EOUTRANGE); - if (src->n_past_msv > UINT32_MAX) defer_return(H3C_EOUTRANGE); - if (src->n_past_bias > UINT32_MAX) defer_return(H3C_EOUTRANGE); - if (src->n_past_vit > UINT32_MAX) defer_return(H3C_EOUTRANGE); - if (src->n_past_fwd > UINT32_MAX) defer_return(H3C_EOUTRANGE); - - dst->nmodels = src->nmodels; - dst->nseqs = src->nseqs; - dst->n_past_msv = src->n_past_msv; - dst->n_past_bias = src->n_past_bias; - dst->n_past_vit = src->n_past_vit; - dst->n_past_fwd = src->n_past_fwd; - - if (src->nhits > UINT32_MAX) defer_return(H3C_EOUTRANGE); - if (src->nreported > UINT32_MAX) defer_return(H3C_EOUTRANGE); - if (src->nincluded > UINT32_MAX) defer_return(H3C_EOUTRANGE); - - dst->nhits = src->nhits; - dst->nreported = src->nreported; - dst->nincluded = src->nincluded; - -defer: - return rc; -} - -int h3client_answer_copy(struct answer *x, struct h3c_result *y) -{ - y->errnum = x->errnum; - if (copy_string(array_size(y->errstr), y->errstr, x->errstr)) return H3C_ENOMEM; - int rc = 0; - if ((rc = copy_stats(&y->content->stats, &x->stats))) return rc; - return copy_tophits(&y->content->tophits, &x->tophits); -} diff --git a/h3client/answer.h b/h3client/answer.h deleted file mode 100644 index a774e07..0000000 --- a/h3client/answer.h +++ /dev/null @@ -1,23 +0,0 @@ -#ifndef H3CLIENT_ANSWER_H -#define H3CLIENT_ANSWER_H - -#include - -struct answer; -struct h3c_result; - -struct answer *h3client_answer_new(void); -void h3client_answer_del(struct answer const *ans); - -unsigned char * h3client_answer_status_data(struct answer *ans); -size_t h3client_answer_status_size(void); -struct hmmd_status const *h3client_answer_status_parse(struct answer *ans); -struct hmmd_status const *h3client_answer_status(struct answer const *ans); - -int h3client_answer_setup_size(struct answer *ans, size_t size); -unsigned char *h3client_answer_data(struct answer *ans); -int h3client_answer_parse(struct answer *ans); -int h3client_answer_parse_error(struct answer *ans); -int h3client_answer_copy(struct answer *ans, struct h3c_result *); - -#endif diff --git a/h3client/argless.c b/h3client/argless.c deleted file mode 100644 index 7900aa9..0000000 --- a/h3client/argless.c +++ /dev/null @@ -1,606 +0,0 @@ -#include "argless.h" - -static bool arg_is_opt(char const *arg); -static bool arg_is_opt_compact(char const *arg); -static bool arg_is_key_opt(char const *arg); -static bool arg_is_key_opt_compact(char const *arg); -static bool arg_is_name_opt(char const *arg); -static bool arg_is_name_opt_compact(char const *arg); -static char const *arg_opt_compact_value(char const *arg); -static bool arg_key_opt_eq(char const *arg, char key); -static bool arg_name_opt_eq(char const *arg, char const *name); - -static bool argvec_check_valid(int argc, char *argv[], - struct argl_option const *opts, bool die); -static void argvec_sort(int argc, char *argv[], struct argl_option const *opts); -static bool argvec_has(int argc, char *argv[], struct argl_option const *opts, - char const *name); -static char const *argvec_get(int argc, char *argv[], - struct argl_option const *opts, char const *name); -static int argvec_nargs(int argc, char *argv[], struct argl_option const *opts); -static char **argvec_args(int argc, char *argv[], - struct argl_option const *opts); - -static char const *al_basename(char const *path); - -static void echo_start(int indent_width); -static void echof(char const *fmt, ...); -static void echos(char const *str); -static void echoc(char c); -static void echor(char const *str); -static void echor2(char const *str, char const *default_value); -static void echo_flush(void); -static void echo_end(void); - -static void help_usage(char const *program, struct argl_option const *opts, - int exit_status); -static void help_help(char const *program, char const *args_doc, - char const *doc, struct argl_option const *opts, - int exit_status); -static void help_version(char const *prog, char const *version, - int exit_status); -static void help_requires_arg(char const *program, char const *arg, - int exit_status); -static void help_unrecognized_arg(char const *program, char const *arg, - int exit_status); - -static struct argl_option const *opts_search(struct argl_option const *opts, - char const *arg); -static struct argl_option const *opts_get(struct argl_option const *opts, - char const *name); -static int opts_count(struct argl_option const *opts); -static bool opt_has_user_default(struct argl_option const *opt); -static char const *opt_get_default(struct argl_option const *opt); -static bool opt_is_flag(struct argl_option const *opt); -static char const *opt_arg_name(struct argl_option const *opt); - -enum -{ - ARGL_WINDOWS, - ARGL_UNIX, - ARGL_MACOS, -}; - -#if defined(_WIN16) || defined(_WIN32) || defined(_WIN64) || defined(__WIN32__) -#define ARGL_OS ZS_WINDOWS -#elif defined(__unix__) || defined(__unix) -#define ARGL_OS ZS_UNIX -#elif defined(__APPLE__) -#define ARGL_OS ARGL_MACOS -#endif - -#ifdef MS_WINDOWS -#define ARGL_PATH_SEP '\\' -#endif - -#ifndef ARGL_PATH_SEP -#define ARGL_PATH_SEP '/' -#endif - -#include - -static char const *al_basename(char const *path) -{ - char *p = strrchr(path, ARGL_PATH_SEP); - return p ? p + 1 : path; -} - -#include -#include - -static size_t arg_long_compact_opt_size(char const *arg); - -static bool arg_is_opt(char const *arg) -{ - return arg_is_key_opt(arg) || arg_is_name_opt(arg); -} - -static bool arg_is_opt_compact(char const *arg) -{ - return arg_is_key_opt(arg) ? arg_is_key_opt_compact(arg) - : arg_is_name_opt_compact(arg); -} - -static bool arg_is_key_opt(char const *arg) -{ - return strlen(arg) > 1 && arg[0] == '-' && arg[1] != '-'; -} - -static bool arg_is_key_opt_compact(char const *arg) -{ - return strlen(arg) > 2 && arg[0] == '-' && arg[1] != '-'; -} - -static bool arg_is_name_opt(char const *arg) -{ - return strlen(arg) > 2 && arg[0] == '-' && arg[1] == '-'; -} - -static bool arg_is_name_opt_compact(char const *arg) -{ - return strchr(arg, '='); -} - -static char const *arg_opt_compact_value(char const *arg) -{ - return arg_is_name_opt_compact(arg) ? strchr(arg, '=') + 1 : arg + 2; -} - -static bool arg_key_opt_eq(char const *arg, char key) { return arg[1] == key; } - -static bool arg_name_opt_eq(char const *arg, char const *name) -{ - size_t size = 0; - if (arg_is_name_opt_compact(arg)) - size = arg_long_compact_opt_size(arg); - else - size = strlen(arg + 2); - - return size == strlen(name) && !strncmp(arg + 2, name, size); -} - -static size_t arg_long_compact_opt_size(char const *arg) -{ - char const *p = strchr(arg, '='); - return p - &arg[2]; -} - -#include -#include - -static struct argl_option const *opts_search(struct argl_option const *opts, - char const *arg) -{ - for (int i = 0; i < opts_count(opts); ++i) - { - if (arg_is_key_opt(arg) && arg_key_opt_eq(arg, opts[i].key)) - return &opts[i]; - if (arg_is_name_opt(arg) && arg_name_opt_eq(arg, opts[i].name)) - return &opts[i]; - } - return NULL; -} - -static struct argl_option const *opts_get(struct argl_option const *opts, - char const *name) -{ - for (int i = 0; i < opts_count(opts); ++i) - { - if (!strcmp(name, opts[i].name)) return &opts[i]; - } - return NULL; -} - -static int opts_count(struct argl_option const *opts) -{ - struct argl_option const *opt = opts; - int size = 0; - while (opt->name) - { - size++; - opt++; - } - return size; -} - -static bool opt_has_user_default(struct argl_option const *opt) -{ - return !opt_is_flag(opt) && opt->arg_def.s.default_value; -} - -static char const *opt_get_default(struct argl_option const *opt) -{ - if (opt_is_flag(opt)) return "false"; - return opt->arg_def.s.default_value; -} - -static bool opt_is_flag(struct argl_option const *opt) -{ - return opt->arg_def.type == ARGL_FLAG_TYPE; -} - -static char const *opt_arg_name(struct argl_option const *opt) -{ - return opt->arg_def.s.name; -} - -#include -#include - -static bool argvec_check_valid(int argc, char *argv[], - struct argl_option const *opts, bool die) -{ - bool force_arg = false; - char const *prg = al_basename(argv[0]); - for (int i = 1; i < argc; ++i) - { - if (!strcmp(argv[i], "--")) force_arg = true; - if (force_arg || !arg_is_opt(argv[i])) continue; - - struct argl_option const *opt = opts_search(opts, argv[i]); - if (!opt) - { - if (die) help_unrecognized_arg(prg, argv[i], EXIT_FAILURE); - return false; - } - - if (!opt_is_flag(opt)) - { - if (arg_is_opt_compact(argv[i])) continue; - if (i + 1 == argc || arg_is_opt(argv[i + 1]) || - !strcmp(argv[i + 1], "--")) - { - if (die) help_requires_arg(prg, argv[i], EXIT_FAILURE); - return false; - } - ++i; - } - else - { - if (arg_is_opt_compact(argv[i])) - { - if (die) help_unrecognized_arg(prg, argv[i], EXIT_FAILURE); - return false; - } - } - } - return true; -} - -static void argvec_sort(int argc, char *argv[], struct argl_option const *opts) -{ - bool force_arg = false; - char *first_arg = 0; - for (int i = 1; i < argc && first_arg != argv[i]; ++i) - { - if (!strcmp(argv[i], "--")) force_arg = true; - if (force_arg || !arg_is_opt(argv[i])) - { - char *curr = argv[i]; - size_t size = argc - 1 - i; - memmove(argv + i, argv + i + 1, sizeof(argv[0]) * size); - argv[argc - 1] = curr; - if (!first_arg) first_arg = curr; - --i; - } - else - { - struct argl_option const *opt = opts_search(opts, argv[i]); - i += !opt_is_flag(opt) && !arg_is_opt_compact(argv[i]); - } - } -} - -static int option_index(int argc, char *argv[], struct argl_option const *opts, - char const *name); - -static bool argvec_has(int argc, char *argv[], struct argl_option const *opts, - char const *name) -{ - return option_index(argc, argv, opts, name) != -1; -} - -static char const *argvec_get(int argc, char *argv[], - struct argl_option const *opts, char const *name) -{ - int i = option_index(argc, argv, opts, name); - if (i == -1) return ""; - - return arg_is_opt_compact(argv[i]) ? arg_opt_compact_value(argv[i]) - : argv[i + 1]; -} - -static int argvec_nargs(int argc, char *argv[], struct argl_option const *opts) -{ - char **p = argvec_args(argc, argv, opts); - return &argv[argc] - p; -} - -static char **argvec_args(int argc, char *argv[], - struct argl_option const *opts) -{ - argvec_sort(argc, argv, opts); - int i = 1; - for (; i < argc; ++i) - { - if (arg_is_opt(argv[i])) - { - struct argl_option const *opt = opts_search(opts, argv[i]); - if (opt) i += !opt_is_flag(opt) && !arg_is_opt_compact(argv[i]); - } - else - break; - } - return argv + i; -} - -static int option_index(int argc, char *argv[], struct argl_option const *opts, - char const *name) -{ - for (int i = 1; i < argc; ++i) - { - if (arg_is_opt(argv[i])) - { - struct argl_option const *opt = opts_search(opts, argv[i]); - if (opt) - { - if (!strcmp(opt->name, name)) return i; - i += !opt_is_flag(opt) && !arg_is_opt_compact(argv[i]); - } - } - } - return -1; -} - -#include -#include -#include -#include -#include - -#define NCOL 80 - -static char buf[NCOL + 1] = {0}; -static size_t pos = 0; -static size_t width = 0; - -static void echo_empty_spaces(int n); -static void vecho(const char *fmt, va_list va); - -static void echo_start(int indent_width) -{ - width = (size_t)indent_width; - pos = 0; - buf[0] = '\0'; -} - -static void echof(char const *fmt, ...) -{ - va_list va; - va_start(va, fmt); - size_t r = vsnprintf(buf + pos, sizeof(buf) - pos, fmt, va); - va_end(va); - - if (pos + r < sizeof buf) - { - pos += r; - return; - } - - buf[pos] = '\0'; - echo_flush(); - - echo_empty_spaces((int)width); - va_start(va, fmt); - vecho(fmt, va); - va_end(va); -} - -static void echos(char const *str) { echof("%s", str); } - -static void echoc(char c) { echof("%c", c); } - -static void echor(char const *str) -{ - size_t size = strlen(str) + 2; - if (sizeof(buf) > pos + size) - { - echo_empty_spaces((int)(width - pos + 2)); - echos(str); - } - else - { - echo_flush(); - echof(" %s", str); - } -} - -static void echor2(char const *str, char const *default_value) -{ - size_t size = strlen(str) + 2; - if (sizeof(buf) > pos + size) - { - echo_empty_spaces((int)(width - pos + 2)); - echof("%s [%s]", str, default_value); - } - else - { - echo_flush(); - echof(" %s [%s]", str, default_value); - } -} - -static void echo_end(void) -{ - if (pos > 0) puts(buf); -} - -static void echo_empty_spaces(int n) -{ - while (--n > 0) - echof("%c", ' '); -} - -static void echo_flush(void) -{ - if (pos > 0) puts(buf); - pos = 0; - buf[0] = '\0'; -} - -static void vecho(const char *fmt, va_list va) -{ - pos += vsnprintf(buf + pos, sizeof(buf) - pos, fmt, va); -} - -#include -#include -#include -#include - -static void display_try_info(char const *progam_name); - -static void help_usage(char const *prog, struct argl_option const *opts, - int exit_status) -{ - echo_start(11); - echof("Usage: %s", prog); - - echos(" [-"); - for (int i = 0; i < opts_count(opts); ++i) - { - if (isprint(opts[i].key)) echoc(opts[i].key); - } - echos("]"); - - for (int i = 0; i < opts_count(opts); ++i) - { - if (isprint(opts[i].key) && !opt_is_flag(opts + i)) - { - echof(" [-%c %s]", opts[i].key, opt_arg_name(opts + i)); - } - if (!opt_is_flag(opts + i)) - echof(" [--%s=%s]", opts[i].name, opt_arg_name(opts + i)); - else - echof(" [--%s]", opts[i].name); - } - - echo_end(); - exit(exit_status); -} - -static void help_help(char const *prog, char const *args_doc, char const *doc, - struct argl_option const *opts, int exit_status) -{ - echo_start(0); - echof("Usage: %s [OPTION...]", prog); - if (args_doc) echof(" %s", args_doc); - echoc('\n'); - echo_end(); - - echo_start(2); - echoc(' '); - char const *start = doc; - char const *end = strchr(doc, ' '); - while (end) - { - echof(" %.*s", (end - start), start); - start = end + 1; - end = strchr(start, ' '); - } - if (strlen(start) > 0) echof(" %s", start); - echo_end(); - - echo_start(0); - echoc('\n'); - echos("Options:"); - echo_end(); - - echo_start(28); - for (int i = 0; i < opts_count(opts); ++i) - { - if (isprint(opts[i].key)) - echof(" -%c, --%s", opts[i].key, opts[i].name); - else - echof(" --%s", opts[i].name); - - if (opt_has_user_default(opts + i)) - echor2(opts[i].arg_doc, opt_get_default(opts + i)); - else - echor(opts[i].arg_doc); - echo_flush(); - } - echo_end(); - exit(exit_status); -} - -static void help_version(char const *prog, char const *version, int exit_status) -{ - echo_start(0); - echof("%s, version %s", prog, version); - echo_end(); - exit(exit_status); -} - -static void help_requires_arg(char const *prog, char const *arg, - int exit_status) -{ - printf("%s: option `%s' requires an argument\n", prog, arg); - display_try_info(prog); - exit(exit_status); -} - -static void help_unrecognized_arg(char const *prog, char const *arg, - int exit_status) -{ - printf("%s: unrecognized option `%s'\n", prog, arg); - display_try_info(prog); - exit(exit_status); -} - -static void display_try_info(char const *prg) -{ - printf("Try `%s --help' or `%s --usage' for more information.\n", prg, prg); -} - -void argl_parse(struct argl *al, int argc, char *argv[]) -{ - al->argc = argc; - al->argv = argv; - if (!argvec_check_valid(argc, argv, al->options, true)) return; - argvec_sort(argc, argv, al->options); - - char const *program = al_basename(argv[0]); - - if (argvec_has(argc, argv, al->options, "usage")) - help_usage(program, al->options, EXIT_SUCCESS); - - if (argvec_has(argc, argv, al->options, "help")) - help_help(program, al->args_doc, al->doc, al->options, EXIT_SUCCESS); - - if (argvec_has(argc, argv, al->options, "version")) - help_version(program, al->version, EXIT_SUCCESS); -} - -bool argl_has(struct argl const *al, char const *name) -{ - int n = al->argc - argvec_nargs(al->argc, al->argv, al->options); - return argvec_has(n, al->argv, al->options, name); -} - -char const *argl_get(struct argl const *al, char const *name) -{ - struct argl_option const *opt = opts_get(al->options, name); - if (!opt) return ""; - - if (opt_is_flag(opt)) return argl_has(al, name) ? "true" : "false"; - - if (argl_has(al, name)) - return argvec_get(al->argc, al->argv, al->options, name); - - char const *value = opt_get_default(opt); - return value ? value : ""; -} - -int argl_nargs(struct argl const *al) -{ - return argvec_nargs(al->argc, al->argv, al->options); -} - -char **argl_args(struct argl const *al) -{ - return argvec_args(al->argc, al->argv, al->options); -} - -void argl_usage(struct argl const *al) { argl_usage2(al, EXIT_FAILURE); } - -void argl_usage2(struct argl const *al, int exit_status) -{ - char const *program = al_basename(al->argv[0]); - help_usage(program, al->options, exit_status); -} - -char const *argl_program(struct argl const *al) -{ - return al_basename(al->argv[0]); -} diff --git a/h3client/argless.h b/h3client/argless.h deleted file mode 100644 index 1ee541f..0000000 --- a/h3client/argless.h +++ /dev/null @@ -1,109 +0,0 @@ -#ifndef ARGLESS_H -#define ARGLESS_H - -#include - -struct argl_option; - -struct argl -{ - struct argl_option const *options; - char const *args_doc; - char const *doc; - char const *version; - - int argc; - char **argv; -}; - -void argl_parse(struct argl *, int argc, char *argv[]); -bool argl_has(struct argl const *, char const *name); -char const *argl_get(struct argl const *, char const *name); -int argl_nargs(struct argl const *); -char **argl_args(struct argl const *); -void argl_usage(struct argl const *); -void argl_usage2(struct argl const *, int exit_status); -char const *argl_program(struct argl const *); - -struct argl_text -{ - char const *name; - char const *default_value; -}; - -struct argl_flag -{ - int : 0; -}; - -struct argl_def -{ - int type; - union - { - struct argl_text s; - struct argl_flag b; - }; -}; - -enum -{ - ARGL_TEXT_TYPE = 0, - ARGL_FLAG_TYPE = 1, -}; - -#define ARGL_TEXT(NAME, DEFAULT) \ - (struct argl_def) \ - { \ - ARGL_TEXT_TYPE, \ - { \ - .s = { NAME, DEFAULT } \ - } \ - } -#define ARGL_FLAG() \ - (struct argl_def) \ - { \ - ARGL_FLAG_TYPE, \ - { \ - { \ - 0 \ - } \ - } \ - } - -struct argl_option -{ - char const *name; - char const key; - struct argl_def arg_def; - char const *arg_doc; -}; - -#define ARGL_NULL ((void *)0) - -#define ARGL_HELP_KEY '?' -#define ARGL_USAGE_KEY -1 -#define ARGL_VERSION_KEY 'V' - -#define ARGL_HELP_OPT \ - { \ - "help", ARGL_HELP_KEY, ARGL_FLAG(), "Give this help list" \ - } -#define ARGL_USAGE_OPT \ - { \ - "usage", ARGL_USAGE_KEY, ARGL_FLAG(), "Give a short usage message" \ - } - -#define ARGL_VERSION_OPT \ - { \ - "version", ARGL_VERSION_KEY, ARGL_FLAG(), "Print program version" \ - } - -#define ARGL_END \ - { \ - 0 \ - } - -#define ARGL_DEFAULT ARGL_HELP_OPT, ARGL_USAGE_OPT, ARGL_VERSION_OPT - -#endif diff --git a/h3client/array_size.h b/h3client/array_size.h deleted file mode 100644 index 04dc738..0000000 --- a/h3client/array_size.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef ARRAY_SIZE_H -#define ARRAY_SIZE_H - -#define array_size(arr) (sizeof(arr) / sizeof((arr)[0])) - -#endif diff --git a/h3client/body.c b/h3client/body.c new file mode 100644 index 0000000..0b73f53 --- /dev/null +++ b/h3client/body.c @@ -0,0 +1,890 @@ +#include "body.h" +#include "posix.h" +#include "bsd.h" +#include "defer_return.h" +#include "h3c_errnum.h" +#include "h3r_domain.h" +#include "h3r_hit.h" +#include "h3r_result.h" +#include "h3r_stats.h" +#include "parse.h" +#include +#include +#include +#include + +enum zsetby +{ + ZSETBY_NTARGETS = 0, + ZSETBY_OPTION = 1, + ZSETBY_FILEINFO = 2 +}; + +struct stats +{ + double Z; + double domZ; + enum zsetby Z_setby; + enum zsetby domZ_setby; + + uint64_t nmodels; + uint64_t nseqs; + uint64_t n_past_msv; + uint64_t n_past_bias; + uint64_t n_past_vit; + uint64_t n_past_fwd; + + uint64_t nhits; + uint64_t nreported; + uint64_t nincluded; + uint64_t *hit_offsets; +}; + +void stats_init(struct stats *x) +{ + x->Z = 0; + x->domZ = 0; + x->Z_setby = 0; + x->domZ_setby = 0; + + x->nmodels = 0; + x->nseqs = 0; + x->n_past_msv = 0; + x->n_past_bias = 0; + x->n_past_vit = 0; + x->n_past_fwd = 0; + + x->nhits = 0; + x->nreported = 0; + x->nincluded = 0; + x->hit_offsets = NULL; +} + +void stats_cleanup(struct stats *x) +{ + free(x->hit_offsets); + stats_init(x); +} + +static int stats_parse(struct stats *x, unsigned char const *head, + unsigned char const *tail, size_t *size) +{ + unsigned char const *old_head = head; + if (tail < head + 14 * 8 + 2) return H3C_EPARSE; + + + (void)parse_double(head); head += 8; // skip elapsed + (void)parse_double(head); head += 8; // skip user + (void)parse_double(head); head += 8; // skip sys + + x->Z = parse_double(head); head += 8; + x->domZ = parse_double(head); head += 8; + + x->Z_setby = parse_flag(head); head += 1; + x->domZ_setby = parse_flag(head); head += 1; + + if (x->Z_setby > ZSETBY_FILEINFO) return H3C_EPARSE; + if (x->domZ_setby > ZSETBY_FILEINFO) return H3C_EPARSE; + + x->nmodels = parse_uint64(head); head += 8; + x->nseqs = parse_uint64(head); head += 8; + x->n_past_msv = parse_uint64(head); head += 8; + x->n_past_bias = parse_uint64(head); head += 8; + x->n_past_vit = parse_uint64(head); head += 8; + x->n_past_fwd = parse_uint64(head); head += 8; + x->nhits = parse_uint64(head); head += 8; + x->nreported = parse_uint64(head); head += 8; + x->nincluded = parse_uint64(head); head += 8; + + if (tail < head + x->nhits * 8) return H3C_EPARSE; + + uint64_t hit_offset0 = parse_uint64(head); head += 8; + size_t hit_offset_size = x->nhits * sizeof(uint64_t); + + if (hit_offset_size == UINT64_MAX && x->nhits > 0) return H3C_EPARSE; + + x->hit_offsets = bsd_reallocf(x->hit_offsets, hit_offset_size); + if (!x->hit_offsets) return H3C_ENOMEM; + + x->hit_offsets[0] = hit_offset0; + for (uint64_t i = 1; i < x->nhits; i++) + { + x->hit_offsets[i] = parse_uint64(head); + head += 8; + } + + *size = (size_t)(head - old_head); + return 0; +} + +struct alidisplay +{ + uint8_t presence; + + char *rfline; + char *mmline; + char *csline; + char *model; + char *mline; + char *aseq; + char *ntseq; + char *ppline; + uint32_t N; + + char *hmmname; + char *hmmacc; + char *hmmdesc; + uint32_t hmmfrom; + uint32_t hmmto; + uint32_t M; + + char *sqname; + char *sqacc; + char *sqdesc; + uint64_t sqfrom; + uint64_t sqto; + uint64_t L; + + size_t memsize; + unsigned char *mem; +}; + +static void alidisplay_init(struct alidisplay *x) +{ + x->presence = 0; + + x->rfline = NULL; + x->mmline = NULL; + x->csline = NULL; + x->model = NULL; + x->mline = NULL; + x->aseq = NULL; + x->ntseq = NULL; + x->ppline = NULL; + x->N = 0; + + x->hmmname = NULL; + x->hmmacc = NULL; + x->hmmdesc = NULL; + x->hmmfrom = 0; + x->hmmto = 0; + x->M = 0; + + x->sqname = NULL; + x->sqacc = NULL; + x->sqdesc = NULL; + x->sqfrom = 0; + x->sqto = 0; + x->L = 0; + + x->memsize = 0; + x->mem = NULL; +} + +static void alidisplay_cleanup(struct alidisplay *x) +{ + free(x->mem); + alidisplay_init(x); +} + +#define SER_BASE_SIZE ((5 * sizeof(int)) + (3 * sizeof(int64_t)) + 1) + +#define RFLINE_PRESENT (1 << 0) +#define MMLINE_PRESENT (1 << 1) +#define CSLINE_PRESENT (1 << 2) +#define PPLINE_PRESENT (1 << 3) +#define ASEQ_PRESENT (1 << 4) +#define NTSEQ_PRESENT (1 << 5) + +static inline bool has_string(unsigned char const *head, + unsigned char const *tail) +{ + char const *string = (char const *)head; + return posix_strnlen(string, tail - head) < (size_t)(tail - head); +} + +static int alidisplay_parse(struct alidisplay *x, unsigned char const *head, + unsigned char const *tail, size_t *size) +{ + int rc = 0; + unsigned char const *old_head = head; + + if (tail < head + 1 + 5 * 4 + 3 * 8) defer_return(H3C_EPARSE); + + size_t obj_size = parse_uint32(head); head += 4; + if (obj_size <= SER_BASE_SIZE) defer_return(H3C_EPARSE); + size_t memsize = (size_t)(obj_size - SER_BASE_SIZE); + + if (!(x->mem = bsd_reallocf(x->mem, memsize))) defer_return(H3C_ENOMEM); + x->memsize = memsize; + + x->N = parse_uint32(head); head += 4; + x->hmmfrom = parse_uint32(head); head += 4; + x->hmmto = parse_uint32(head); head += 4; + x->M = parse_uint32(head); head += 4; + x->sqfrom = parse_uint64(head); head += 8; + x->sqto = parse_uint64(head); head += 8; + x->L = parse_uint64(head); head += 8; + + x->presence = parse_flag(head); head += 1; + + if (tail < head + memsize) defer_return(H3C_EPARSE); + memcpy(x->mem, head, memsize); + head += memsize; + + unsigned char *mem = x->mem; + unsigned char *memtail = mem + memsize; + + if (x->presence & RFLINE_PRESENT && !has_string(mem, memtail)) defer_return(H3C_EPARSE); + x->rfline = x->presence & RFLINE_PRESENT ? (char *)mem : NULL; + mem += x->presence & RFLINE_PRESENT ? strlen(x->rfline) + 1: 0; + + if (x->presence & MMLINE_PRESENT && !has_string(mem, memtail)) defer_return(H3C_EPARSE); + x->mmline = x->presence & MMLINE_PRESENT ? (char *)mem : NULL; + mem += x->presence & MMLINE_PRESENT ? strlen(x->mmline) + 1: 0; + + if (x->presence & CSLINE_PRESENT && !has_string(mem, memtail)) defer_return(H3C_EPARSE); + x->csline = x->presence & CSLINE_PRESENT ? (char *)mem : NULL; + mem += x->presence & CSLINE_PRESENT ? strlen(x->csline) + 1: 0; + + if (!has_string(mem, memtail)) defer_return(H3C_EPARSE); + x->model = (char *)mem; mem += strlen(x->model) + 1; + + if (!has_string(mem, memtail)) defer_return(H3C_EPARSE); + x->mline = (char *)mem; mem += strlen(x->mline) + 1; + + if (x->presence & ASEQ_PRESENT && !has_string(mem, memtail)) defer_return(H3C_EPARSE); + x->aseq = x->presence & ASEQ_PRESENT ? (char *)mem : NULL; + mem += x->presence & ASEQ_PRESENT ? strlen(x->aseq) + 1: 0; + + if (x->presence & NTSEQ_PRESENT && !has_string(mem, memtail)) defer_return(H3C_EPARSE); + x->ntseq = x->presence & NTSEQ_PRESENT ? (char *)mem : NULL; + mem += x->presence & NTSEQ_PRESENT ? strlen(x->ntseq) + 1: 0; + + if (x->presence & PPLINE_PRESENT && !has_string(mem, memtail)) defer_return(H3C_EPARSE); + x->ppline = x->presence & PPLINE_PRESENT ? (char *)mem : NULL; + mem += x->presence & PPLINE_PRESENT ? strlen(x->ppline) + 1: 0; + + if (!has_string(mem, memtail)) defer_return(H3C_EPARSE); + x->hmmname = (char *)mem; mem += strlen(x->hmmname) + 1; + + if (!has_string(mem, memtail)) defer_return(H3C_EPARSE); + x->hmmacc = (char *)mem; mem += strlen(x->hmmacc) + 1; + + if (!has_string(mem, memtail)) defer_return(H3C_EPARSE); + x->hmmdesc = (char *)mem; mem += strlen(x->hmmdesc) + 1; + + if (!has_string(mem, memtail)) defer_return(H3C_EPARSE); + x->sqname = (char *)mem; mem += strlen(x->sqname) + 1; + + if (!has_string(mem, memtail)) defer_return(H3C_EPARSE); + x->sqacc = (char *)mem; mem += strlen(x->sqacc) + 1; + + if (!has_string(mem, memtail)) defer_return(H3C_EPARSE); + x->sqdesc = (char *)mem; mem += strlen(x->sqdesc) + 1; + + *size = (size_t)(head - old_head); + return 0; + +defer: + alidisplay_cleanup(x); + return rc; +} + +struct domain +{ + uint32_t ienv; + uint32_t jenv; + uint32_t iali; + uint32_t jali; + // The following two members seems to be receiving + // random numbers from daemon end. Skip them. + // int64_t iorf, jorf; + float envsc; + float domcorrection; + float dombias; + float oasc; + float bitscore; + double lnP; + bool is_reported; + bool is_included; + uint32_t scores_size; + float *pos_score; + struct alidisplay ad; +}; + +static void domain_init(struct domain *x) +{ + x->ienv = 0; + x->jenv = 0; + x->iali = 0; + x->jali = 0; + // The following two members seems to be receiving + // random numbers from daemon end. Skip them. + // int64_t iorf, jorf; + x->envsc = 0; + x->domcorrection = 0; + x->dombias = 0; + x->oasc = 0; + x->bitscore = 0; + x->lnP = 0; + x->is_reported = false; + x->is_included = false; + x->scores_size = 0; + x->pos_score = NULL; + alidisplay_init(&x->ad); +} + +static void domain_cleanup(struct domain *x) +{ + free(x->pos_score); + alidisplay_cleanup(&x->ad); + domain_init(x); +} + +static int domain_parse(struct domain *x, unsigned char const *head, + unsigned char const *tail, size_t *size) +{ + int rc = 0; + unsigned char const *old_head = head; + + if (tail < head + 4 + 6 * 8) defer_return(H3C_EPARSE); + + // Skips object size + (void)parse_uint32(head) ; head += 4; + x->ienv = parse_uint64(head); head += 8; + x->jenv = parse_uint64(head); head += 8; + x->iali = parse_uint64(head); head += 8; + x->jali = parse_uint64(head); head += 8; + + // Skips iorf and jorf. + (void)parse_uint64(head); head += 8; + (void)parse_uint64(head); head += 8; + + if (tail < head + 8 * 4 + 8) defer_return(H3C_EPARSE); + + x->envsc = parse_float(head) ; head += 4; + x->domcorrection = parse_float(head) ; head += 4; + x->dombias = parse_float(head) ; head += 4; + x->oasc = parse_float(head) ; head += 4; + x->bitscore = parse_float(head) ; head += 4; + x->lnP = parse_double(head); head += 8; + x->is_reported = parse_uint32(head); head += 4; + x->is_included = parse_uint32(head); head += 4; + + uint32_t scores_size = parse_uint32(head); head += 4; + + if (scores_size > x->scores_size) + { + size_t size = scores_size * sizeof(float); + if (!(x->pos_score = bsd_reallocf(x->pos_score, size))) + defer_return(H3C_EPARSE); + x->scores_size = scores_size; + } + else + x->scores_size = scores_size; + + if (tail < head + x->scores_size * 4) defer_return(H3C_EPARSE); + for (uint32_t i = 0; i < x->scores_size; i++) + { + x->pos_score[i] = parse_float(head); head += 4; + } + + size_t n = 0; + if ((rc = alidisplay_parse(&x->ad, head, tail, &n))) defer_return(rc); + head += n; + + *size = (size_t)(head - old_head); + return 0; + +defer: + domain_cleanup(x); + return rc; +} + +struct hit +{ + char *name; + char *acc; + char *desc; + // The following members seem to be receiving + // random numbers from daemon end. Skip them. + // int window_length; + double sortkey; + + float score; + float pre_score; + float sum_score; + + double lnP; + double pre_lnP; + double sum_lnP; + + float nexpected; + uint32_t nregions; + uint32_t nclustered; + uint32_t noverlaps; + uint32_t nenvelopes; + uint32_t ndom; + + uint32_t flags; + uint32_t nreported; + uint32_t nincluded; + uint32_t best_domain; + + // Skip it. + // uint64_t seqidx; + // The following member seems to be receiving + // random numbers from daemon end. Skip it. + // uint64_t subseq_start; + + struct domain *dcl; +}; + +static void hit_init(struct hit *x) +{ + x->name = NULL; + x->acc = NULL; + x->desc = NULL; + // The following members seem to be receiving + // random numbers from daemon end. Skip them. + // int window_length; + x->sortkey = 0; + + x->score = 0; + x->pre_score = 0; + x->sum_score = 0; + + x->lnP = 0; + x->pre_lnP = 0; + x->sum_lnP = 0; + + x->nexpected = 0; + x->nregions = 0; + x->nclustered = 0; + x->noverlaps = 0; + x->nenvelopes = 0; + x->ndom = 0; + + x->flags = 0; + x->nreported = 0; + x->nincluded = 0; + x->best_domain = 0; + + x->dcl = NULL; +} + +static void hit_cleanup(struct hit *x) +{ + for (uint32_t i = 0; i < x->ndom; i++) + domain_cleanup(x->dcl + i); + hit_init(x); +} + +static int copy_string(char **dst, char const *src) +{ + if (!src) return 0; + size_t size = strlen(src) + 1; + if (!(*dst = bsd_reallocf(*dst, size))) return H3C_ENOMEM; + memcpy(*dst, src, size); + return 0; +} + +#define ACC_PRESENT (1 << 0) +#define DESC_PRESENT (1 << 1) + +static int hit_parse(struct hit *x, unsigned char const *head, + unsigned char const *tail, size_t *size) +{ + int rc = 0; + unsigned char const *old_head = head; + + if (tail < head + 2 * 4) defer_return(H3C_EPARSE); + + // Skips object size + (void)parse_uint32(head); head += 4; + + // Skips window_length for now + (void)parse_uint32(head); head += 4; + + if (tail < head + 4 * 8 + 3 * 4) defer_return(H3C_EPARSE); + x->sortkey = parse_double(head); head += 8; + x->score = parse_float(head) ; head += 4; + x->pre_score = parse_float(head) ; head += 4; + x->sum_score = parse_float(head) ; head += 4; + + x->lnP = parse_double(head); head += 8; + x->pre_lnP = parse_double(head); head += 8; + x->sum_lnP = parse_double(head); head += 8; + + if (tail < head + 6 * 4) defer_return(H3C_EPARSE); + x->nexpected = parse_float(head) ; head += 4; + x->nregions = parse_uint32(head); head += 4; + x->nclustered = parse_uint32(head); head += 4; + x->noverlaps = parse_uint32(head); head += 4; + x->nenvelopes = parse_uint32(head); head += 4; + uint32_t ndom = parse_uint32(head); head += 4; + + if (tail < head + 4 * 4 + 2 * 8) defer_return(H3C_EPARSE); + x->flags = parse_uint32(head); head += 4; + x->nreported = parse_uint32(head); head += 4; + x->nincluded = parse_uint32(head); head += 4; + x->best_domain = parse_uint32(head); head += 4; + // Skips seqidx + (void)parse_uint64(head); head += 8; + // Skips subseq_start for now + (void)parse_uint64(head); head += 8; + + if (tail < head + 1) defer_return(H3C_EPARSE); + uint8_t presence = parse_flag(head); head += 1; + + if (!has_string(head, tail)) defer_return(H3C_EPARSE); + if ((rc = copy_string(&x->name, (char const *)head))) defer_return(rc); + head += strlen(x->name) + 1; + + if (presence & ACC_PRESENT) + { + if (!has_string(head, tail)) defer_return(H3C_EPARSE); + if ((rc = copy_string(&x->acc, (char const *)head))) defer_return(rc); + head += strlen(x->acc) + 1; + } + + if (presence & DESC_PRESENT) + { + if (!has_string(head, tail)) defer_return(H3C_EPARSE); + if ((rc = copy_string(&x->desc, (char const *)head))) defer_return(rc); + head += strlen(x->desc) + 1; + } + + if (ndom > x->ndom) + { + if (!(x->dcl = bsd_reallocf(x->dcl, ndom * sizeof(*x->dcl)))) defer_return(H3C_ENOMEM); + for (uint32_t i = x->ndom; i < ndom; i++) + { + domain_init(x->dcl + i); + ++x->ndom; + } + } + else + { + for (uint32_t i = ndom; i < x->ndom; i++) + domain_cleanup(x->dcl + i); + x->ndom = ndom; + } + + for (uint32_t i = 0; i < x->ndom; i++) + { + size_t n = 0; + if ((rc = domain_parse(x->dcl + i, head, tail, &n))) defer_return(rc); + head += n; + } + + *size = (size_t)(head - old_head); + return 0; + +defer: + hit_cleanup(x); + return rc; +} + +struct tophits +{ + struct hit **hit; + struct hit *unsrt; + uint64_t nhits; + uint64_t nreported; + uint64_t nincluded; + bool is_sorted_by_sortkey; + bool is_sorted_by_seqidx; +}; + +static void tophits_init(struct tophits *x) +{ + x->hit = NULL; + x->unsrt = NULL; + x->nhits = 0; + x->nreported = 0; + x->nincluded = 0; + x->is_sorted_by_sortkey = false; + x->is_sorted_by_seqidx = false; +} + +static void tophits_cleanup(struct tophits *x) +{ + for (uint64_t i = 0; i < x->nhits; ++i) + hit_cleanup(x->unsrt + i); + free(x->hit); + free(x->unsrt); + tophits_init(x); +} + +static int tophits_parse(struct tophits *x, unsigned char const *head, + unsigned char const *tail, size_t *size, uint64_t nhits, + uint64_t nreported, uint64_t nincluded) +{ + int rc = 0; + unsigned char const *old_head = head; + + if (nhits > x->nhits) + { + if (!(x->hit = bsd_reallocf(x->hit, sizeof(struct hit *) * nhits))) + defer_return(H3C_ENOMEM); + + if (!(x->unsrt = bsd_reallocf(x->unsrt, sizeof(struct hit) * nhits))) + defer_return(H3C_ENOMEM); + + for (uint64_t i = x->nhits; i < nhits; ++i) + { + hit_init(x->unsrt + i); + ++x->nhits; + } + } + + x->nreported = nreported; + x->nincluded = nincluded; + x->is_sorted_by_seqidx = false; + x->is_sorted_by_sortkey = true; + + for (uint64_t i = 0; i < nhits; ++i) + { + int rc = 0; + size_t n = 0; + if ((rc = hit_parse(x->unsrt + i, head, tail, &n))) defer_return(rc); + head += n; + x->hit[i] = x->unsrt + i; + } + + *size = (size_t)(head - old_head); + return 0; + +defer: + tophits_cleanup(x); + return rc; +} + +struct body +{ + struct stats stats; + struct tophits tophits; +}; + +struct body *body_new(void) +{ + struct body *x = malloc(sizeof(struct body)); + if (!x) return NULL; + tophits_init(&x->tophits); + return x; +} + +int body_parse(struct body *x, size_t size, + unsigned char const buffer[size]) +{ + int rc = 0; + size_t n = 0; + unsigned char const *head = buffer; + unsigned char const *tail = buffer + size; + + if ((rc = stats_parse(&x->stats, head, tail, &n))) defer_return(rc); + head += n; + + if ((rc = tophits_parse(&x->tophits, head, tail, &n, x->stats.nhits, + x->stats.nreported, x->stats.nincluded))) + defer_return(rc); + head += n; + + if (head != tail) defer_return(H3C_EPARSE); + + return rc; + +defer: + stats_cleanup(&x->stats); + tophits_cleanup(&x->tophits); + return rc; +} + +static int copy_stats(struct h3r_stats *dst, struct stats const *src) +{ + dst->Z = src->Z; + dst->domZ = src->domZ; + + dst->Z_setby = (enum h3r_zsetby)src->Z_setby; + dst->domZ_setby = (enum h3r_zsetby)src->domZ_setby; + + if (src->nmodels > UINT32_MAX) return H3C_EOUTRANGE; + if (src->nseqs > UINT32_MAX) return H3C_EOUTRANGE; + if (src->n_past_msv > UINT32_MAX) return H3C_EOUTRANGE; + if (src->n_past_bias > UINT32_MAX) return H3C_EOUTRANGE; + if (src->n_past_vit > UINT32_MAX) return H3C_EOUTRANGE; + if (src->n_past_fwd > UINT32_MAX) return H3C_EOUTRANGE; + + dst->nmodels = src->nmodels; + dst->nseqs = src->nseqs; + dst->n_past_msv = src->n_past_msv; + dst->n_past_bias = src->n_past_bias; + dst->n_past_vit = src->n_past_vit; + dst->n_past_fwd = src->n_past_fwd; + + if (src->nhits > UINT32_MAX) return H3C_EOUTRANGE; + if (src->nreported > UINT32_MAX) return H3C_EOUTRANGE; + if (src->nincluded > UINT32_MAX) return H3C_EOUTRANGE; + + dst->nhits = src->nhits; + dst->nreported = src->nreported; + dst->nincluded = src->nincluded; + + return 0; +} + +static int copy_alidisplay(struct h3r_alidisplay *dst, + struct alidisplay const *src) +{ + dst->presence = src->presence; + + if (copy_string(&dst->rfline, src->rfline)) return H3C_ENOMEM; + if (copy_string(&dst->mmline, src->mmline)) return H3C_ENOMEM; + if (copy_string(&dst->csline, src->csline)) return H3C_ENOMEM; + if (copy_string(&dst->model, src->model)) return H3C_ENOMEM; + if (copy_string(&dst->mline, src->mline)) return H3C_ENOMEM; + if (copy_string(&dst->aseq, src->aseq)) return H3C_ENOMEM; + if (copy_string(&dst->ntseq, src->ntseq)) return H3C_ENOMEM; + if (copy_string(&dst->ppline, src->ppline)) return H3C_ENOMEM; + dst->N = src->N; + + if (copy_string(&dst->hmmname, src->hmmname)) return H3C_ENOMEM; + if (copy_string(&dst->hmmacc, src->hmmacc)) return H3C_ENOMEM; + if (copy_string(&dst->hmmdesc, src->hmmdesc)) return H3C_ENOMEM; + dst->hmmfrom = src->hmmfrom; + dst->hmmto = src->hmmto; + dst->M = src->M; + + if (src->sqfrom > UINT32_MAX) return H3C_EOUTRANGE; + if (src->sqto > UINT32_MAX) return H3C_EOUTRANGE; + if (src->L > UINT32_MAX) return H3C_EOUTRANGE; + + if (copy_string(&dst->sqname, src->sqname)) return H3C_ENOMEM; + if (copy_string(&dst->sqacc, src->sqacc)) return H3C_ENOMEM; + if (copy_string(&dst->sqdesc, src->sqdesc)) return H3C_ENOMEM; + dst->sqfrom = src->sqfrom; + dst->sqto = src->sqto; + dst->L = src->L; + + return 0; +} + +static int copy_domain(struct h3r_domain *dst, struct domain const *src) +{ + int rc = 0; + if ((rc = h3r_domain_setup(dst, src->scores_size))) defer_return(H3C_EH3RESULT); + + if (src->ienv > UINT32_MAX) defer_return(H3C_EOUTRANGE); + if (src->jenv > UINT32_MAX) defer_return(H3C_EOUTRANGE); + if (src->iali > UINT32_MAX) defer_return(H3C_EOUTRANGE); + if (src->jali > UINT32_MAX) defer_return(H3C_EOUTRANGE); + + dst->ienv = src->ienv; + dst->jenv = src->jenv; + dst->iali = src->iali; + dst->jali = src->jali; + dst->envsc = src->envsc; + dst->domcorrection = src->domcorrection; + dst->dombias = src->dombias; + dst->oasc = src->oasc; + dst->bitscore = src->bitscore; + dst->lnP = src->lnP; + dst->is_reported = src->is_reported; + dst->is_included = src->is_included; + + if (src->scores_size > UINT32_MAX) defer_return(H3C_EOUTRANGE); + memcpy(dst->pos_score, src->pos_score, dst->pos_score_size * 4); + + if ((rc = copy_alidisplay(&dst->ad, &src->ad))) defer_return(rc); + + return 0; + +defer: + h3r_domain_cleanup(dst); + return rc; +} + +static int copy_hit(struct h3r_hit *dst, struct hit const *src) +{ + int rc = 0; + if (h3r_hit_setup(dst, src->ndom)) defer_return(H3C_EH3RESULT); + + if (copy_string(&dst->name, src->name)) defer_return(H3C_ENOMEM); + if (copy_string(&dst->acc, src->acc)) defer_return(H3C_ENOMEM); + if (copy_string(&dst->desc, src->desc)) defer_return(H3C_ENOMEM); + + dst->sortkey = src->sortkey; + + dst->score = src->score; + dst->pre_score = src->pre_score; + dst->sum_score = src->sum_score; + + dst->lnP = src->lnP; + dst->pre_lnP = src->pre_lnP; + dst->sum_lnP = src->sum_lnP; + + dst->nexpected = src->nexpected; + dst->nregions = src->nregions; + dst->nclustered = src->nclustered; + dst->noverlaps = src->noverlaps; + dst->nenvelopes = src->nenvelopes; + + dst->flags = src->flags; + dst->nreported = src->nreported; + dst->nincluded = src->nincluded; + dst->best_domain = src->best_domain; + + for (unsigned i = 0; i < dst->ndomains; ++i) + { + if ((rc = copy_domain(dst->domains + i, src->dcl + i))) defer_return(rc); + } + + return 0; + +defer: + h3r_hit_cleanup(dst); + return rc; +} + +static int copy_tophits(struct h3r_tophits *dst, struct tophits const *src) +{ + int rc = 0; + if (h3r_tophits_setup(dst, src->nhits)) defer_return(H3C_EH3RESULT); + + dst->nreported = src->nreported; + dst->nincluded = src->nincluded; + dst->is_sorted_by_sortkey = src->is_sorted_by_sortkey; + dst->is_sorted_by_seqidx = src->is_sorted_by_seqidx; + + for (unsigned long i = 0; i < src->nhits; ++i) + { + if ((rc = copy_hit(dst->hits + i, src->hit[i]))) defer_return(rc); + } + + return 0; + +defer: + h3r_tophits_cleanup(dst); + return rc; +} + +int body_store(struct body *x, struct h3r *r) +{ + int rc = 0; + + if ((rc = copy_stats(&r->stats, &x->stats))) return rc; + if ((rc = copy_tophits(&r->tophits, &x->tophits))) return rc; + + return rc; +} + +void body_del(struct body const *x) +{ + if (x) + { + tophits_cleanup((struct tophits *)&x->tophits); + } + free((void *)x); +} diff --git a/h3client/body.h b/h3client/body.h new file mode 100644 index 0000000..99a2223 --- /dev/null +++ b/h3client/body.h @@ -0,0 +1,14 @@ +#ifndef BODY_H +#define BODY_H + +#include + +struct body; +struct h3r; + +struct body *body_new(void); +int body_parse(struct body *, size_t size, unsigned char const buffer[size]); +int body_store(struct body *, struct h3r *); +void body_del(struct body const *); + +#endif diff --git a/h3client/bsd.h b/h3client/bsd.h index c248e23..1855f9c 100644 --- a/h3client/bsd.h +++ b/h3client/bsd.h @@ -6,9 +6,7 @@ static inline void *bsd_reallocf(void *ptr, size_t size) { - if (size <= 0) return NULL; void *new_ptr = realloc(ptr, size); - if (!new_ptr) free(ptr); return new_ptr; } diff --git a/h3client/buff.c b/h3client/buff.c deleted file mode 100644 index 509457e..0000000 --- a/h3client/buff.c +++ /dev/null @@ -1,31 +0,0 @@ -#include "buff.h" -#include "h3c_errno.h" -#include -#include - -struct buff *h3client_buff_new(size_t capacity) -{ - assert(capacity > 0); - - struct buff *buff = malloc(sizeof(struct buff) + capacity); - if (!buff) return 0; - - buff->size = 0; - buff->capacity = capacity; - return buff; -} - -int h3client_buff_ensure(struct buff **buff, size_t capacity) -{ - if (capacity > (*buff)->capacity) - { - struct buff *tmp = realloc(*buff, sizeof(*tmp) + capacity); - if (!tmp) return H3C_ENOMEM; - - *buff = tmp; - (*buff)->capacity = capacity; - } - return 0; -} - -void h3client_buff_del(struct buff const *buff) { free((void *)buff); } diff --git a/h3client/buff.h b/h3client/buff.h deleted file mode 100644 index 6ab6939..0000000 --- a/h3client/buff.h +++ /dev/null @@ -1,17 +0,0 @@ -#ifndef BUFF_H -#define BUFF_H - -#include - -struct buff -{ - size_t size; - size_t capacity; - unsigned char data[]; -}; - -struct buff *h3client_buff_new(size_t capacity); -int h3client_buff_ensure(struct buff **buff, size_t capacity); -void h3client_buff_del(struct buff const *buff); - -#endif diff --git a/h3client/cco.h b/h3client/cco.h deleted file mode 100644 index 3669e4d..0000000 --- a/h3client/cco.h +++ /dev/null @@ -1,617 +0,0 @@ -#ifndef CCO_H -#define CCO_H - -/* ---- cco_compiler module begin ------------------------------------------- */ -#ifndef __has_builtin -#define __has_builtin(x) (0) -#endif -/* ---- cco_compiler module end --------------------------------------------- */ - -/* ---- cco_of module begin ------------------------------------------------- */ -#include - -/** - * cco_of - cast a member of a structure out to the containing - * structure - * @ptr: the pointer to the member. - * @type: the type of the container struct this is embedded in. - * @member: the name of the member within the struct. - * - */ -#define cco_of(ptr, type, member) \ - ({ \ - char *__mptr = (char *)(ptr); \ - ((type *)(__mptr - offsetof(type, member))); \ - }) - -/** - * cco_of_safe - cast a member of a structure out to the containing - * structure - * @ptr: the pointer to the member. - * @type: the type of the container struct this is embedded in. - * @member: the name of the member within the struct. - * - * Return NULL if ptr is NULL. - */ -#define cco_of_safe(ptr, type, member) \ - ({ \ - char *__mptr = (char *)(ptr); \ - __mptr == NULL ? (type *)__mptr \ - : ((type *)(__mptr - offsetof(type, member))); \ - }) -/* ---- cco_of module end --------------------------------------------------- */ - -/* ---- cco_hash_support module begin --------------------------------------- */ -#include - -/** - * __cco_fls32 - find last (most-significant) bit set - * @x: the word to search - * - * This is defined the same way as ffs. - * Note __cco_fls32(1) = 1, __cco_fls32(0x80000000) = 32. - * - * Undefined if no set bit exists, so code should check against 0 first. - */ -static inline unsigned __cco_fls32(uint32_t x) -{ - -#if __has_builtin(__builtin_clz) - return (unsigned)((int)sizeof(int) * 8 - __builtin_clz(x)); -#else - unsigned r = 32; - - if (!(x & 0xffff0000u)) - { - x <<= 16; - r -= 16; - } - if (!(x & 0xff000000u)) - { - x <<= 8; - r -= 8; - } - if (!(x & 0xf0000000u)) - { - x <<= 4; - r -= 4; - } - if (!(x & 0xc0000000u)) - { - x <<= 2; - r -= 2; - } - if (!(x & 0x80000000u)) - { - x <<= 1; - r -= 1; - } - return r; -#endif -} - -/** - * __cco_fls64 - find last (most-significant) set bit in a long word - * @x: the word to search - * - * Undefined if no set bit exists, so code should check against 0 first. - */ -static inline unsigned __cco_fls64(uint64_t x) -{ - -#if __has_builtin(__builtin_clzl) - uint32_t h = (uint32_t)(x >> 32); - return h ? __cco_fls32(h) + 32 : __cco_fls32((uint32_t)x); -#else - return (unsigned)((int)sizeof(long) * 8 - __builtin_clzl(x)); -#endif -} - -/* - * Force a compilation error if condition is true, but also produce a - * result (of value 0 and type int), so the expression can be used - * e.g. in a structure initializer (or where-ever else comma expressions - * aren't permitted). - */ -#define __CCO_BUILD_BUG_ON_ZERO(e) ((int)(sizeof(struct { int : (-!!(e)); }))) - -/* Are two types/vars the same type (ignoring qualifiers)? */ -#define __cco_same_type(a, b) \ - __builtin_types_compatible_p(__typeof__(a), __typeof__(b)) - -/* &a[0] degrades to a pointer: a different type from an array */ -#define __cco_must_be_array(a) \ - __CCO_BUILD_BUG_ON_ZERO(__cco_same_type((a), &(a)[0])) - -#define __CCO_ARRAY_SIZE(arr) \ - (sizeof(arr) / sizeof((arr)[0]) + __cco_must_be_array(arr)) - -#define __CCO_UNSIGNED(x) \ - _Generic((x), \ - char: (unsigned char)(x), \ - signed char: (unsigned char)(x), \ - short: (unsigned short)(x), \ - int: (unsigned int)(x), \ - long: (unsigned long)(x), \ - long long: (unsigned long long)(x), \ - default: (unsigned int)(x)) - -/** - * __cco_ilog2 - log base 2 of 32-bit or a 64-bit unsigned value - * @n: parameter - * - * constant-capable log of base 2 calculation - * - this can be used to initialise global variables from constant data, hence - * the massive ternary operator construction - * - * selects the appropriately-sized optimised version depending on sizeof(n) - */ -#define __cco_ilog2(x) \ - (__builtin_constant_p(x) ? ((x) < 2 ? 0 : 63 - __builtin_clzll(x)) \ - : sizeof(x) <= 4 ? __cco_ilog2_u32(x) \ - : __cco_ilog2_u64(x)) - -static inline unsigned __cco_ilog2_u32(uint32_t n) -{ - return __cco_fls32(n) - 1; -} - -static inline unsigned __cco_ilog2_u64(uint64_t n) -{ - return __cco_fls64(n) - 1; -} - -#define __CCO_GOLDEN_RATIO_32 0x61C88647 -#define __CCO_GOLDEN_RATIO_64 0x61C8864680B583EBull - -static inline uint32_t cco_hash_32(uint32_t val, unsigned bits) -{ - /* High bits are more random, so use them. */ - return val * __CCO_GOLDEN_RATIO_32 >> (32 - bits); -} - -static inline uint32_t cco_hash_64(uint64_t val, unsigned bits) -{ - /* High bits are more random, so use them. */ - return (uint32_t)(val * __CCO_GOLDEN_RATIO_64 >> (64 - bits)); -} - -/* Use cco_hash_32 when possible to allow for fast 32bit hashing in 64bit - * kernels. - */ -#define cco_hash_min(x, bits) \ - (sizeof(x) <= 4 ? cco_hash_32(__CCO_UNSIGNED(x), bits) \ - : cco_hash_64(__CCO_UNSIGNED(x), bits)) - -#define CCO_HASH_SIZE(name) (__CCO_ARRAY_SIZE(name)) -#define CCO_HASH_BITS(name) __cco_ilog2(CCO_HASH_SIZE(name)) -/* ---- cco_hash_support module end ----------------------------------------- */ - -/* ---- cco_node module begin ----------------------------------------------- */ -#include - -struct cco_node -{ - struct cco_node *next; -}; - -#define CCO_NODE_INIT() \ - { \ - NULL \ - } - -static inline void cco_node_add_next(struct cco_node *where, - struct cco_node *novel) -{ - novel->next = where->next; - where->next = novel; -} - -static inline void cco_node_del(struct cco_node *prev, struct cco_node *node) -{ - prev->next = node->next; - node->next = NULL; -} - -static inline void cco_node_init(struct cco_node *node) { node->next = NULL; } -/* ---- cco_node module end ------------------------------------------------- */ - -/* ---- cco_hnode module begin ---------------------------------------------- */ -#include - -struct cco_hnode -{ - struct cco_hnode *next, **pprev; -}; - -#define CCO_HNODE_INIT() \ - { \ - NULL, NULL \ - } - -/** - * cco_hnode_unhashed - Has node been removed from list and reinitialized? - * @h: Node to be checked - * - * Not that not all removal functions will leave a node in unhashed - * state. - */ -static inline int cco_hnode_unhashed(const struct cco_hnode *h) -{ - return !h->pprev; -} - -static inline void __cco_hnode_del(struct cco_hnode *n) -{ - struct cco_hnode *next = n->next; - struct cco_hnode **pprev = n->pprev; - - *pprev = next; - if (next) next->pprev = pprev; -} - -static inline void cco_hnode_init(struct cco_hnode *h) -{ - h->next = NULL; - h->pprev = NULL; -} - -/** - * cco_hnode_del_init - Delete the specified hnode from its list and - * initialize - * @n: Node to delete. - * - * Note that this function leaves the node in unhashed state. - */ -static inline void cco_hnode_del_init(struct cco_hnode *n) -{ - if (!cco_hnode_unhashed(n)) - { - __cco_hnode_del(n); - cco_hnode_init(n); - } -} -/* ---- cco_hnode module end ------------------------------------------------ */ - -/* ---- cco_hlist module begin ---------------------------------------------- */ -struct cco_hlist -{ - struct cco_hnode *first; -}; - -#define CCO_HLIST_INIT(ptr) ((ptr)->first = NULL) - -/** - * cco_hlist_empty - Is the specified hlist structure an empty hlist? - * @h: Structure to check. - */ -static inline int cco_hlist_empty(const struct cco_hlist *h) -{ - return !h->first; -} - -/** - * __cco_hlist_add - add a new entry at the beginning of the hlist - * @n: new entry to be added - * @h: hlist head to add it after - * - * Insert a new entry after the specified head. - * This is good for implementing stacks. - */ -static inline void __cco_hlist_add(struct cco_hnode *n, struct cco_hlist *h) -{ - struct cco_hnode *first = h->first; - n->next = first; - if (first) first->pprev = &n->next; - h->first = n; - n->pprev = &h->first; -} - -/** - * cco_hlist_unhashed - Has node been removed from list and reinitialized? - * @h: Node to be checked - * - * Not that not all removal functions will leave a node in unhashed - * state. For example, hlist_nulls_del_init_rcu() does leave the - * node in unhashed state, but hlist_nulls_del() does not. - */ -static inline int cco_hlist_unhashed(struct cco_hnode const *h) -{ - return !h->pprev; -} - -#define cco_hlist_entry(ptr, type, member) cco_of(ptr, type, member) - -#define cco_hlist_entry_safe(ptr, type, member) \ - ({ \ - __typeof__(ptr) ____ptr = (ptr); \ - ____ptr ? cco_hlist_entry(____ptr, type, member) : NULL; \ - }) - -/** - * __cco_hlist_for_each_entry - iterate over list of given type - * @pos: the type * to use as a loop cursor. - * @head: the head for your list. - * @member: the name of the hnode within the struct. - */ -#define __cco_hlist_for_each_entry(pos, head, member) \ - for (pos = cco_hlist_entry_safe((head)->first, __typeof__(*(pos)), member); \ - pos; pos = cco_hlist_entry_safe((pos)->member.next, __typeof__(*(pos)), \ - member)) - -/** - * __cco_hlist_for_each_entry_safe - iterate over list of given type safe - * against removal of list entry - * @pos: the type * to use as a loop cursor. - * @n: a &struct hnode to use as temporary storage - * @head: the head for your list. - * @member: the name of the hnode within the struct. - */ -#define __cco_hlist_for_each_entry_safe(pos, n, head, member) \ - for (pos = cco_hlist_entry_safe((head)->first, __typeof__(*pos), member); \ - pos && ({ \ - n = pos->member.next; \ - 1; \ - }); \ - pos = cco_hlist_entry_safe(n, __typeof__(*pos), member)) -/* ---- cco_hlist module end ------------------------------------------------ */ - -/* ---- cco_hash module begin ----------------------------------------------- */ -#include -#include -#include - -#define CCO_HASH_DECLARE(name, bits) struct cco_hlist name[1 << (bits)] - -/** - * cco_hash_init - initialize a hash table - * @ht: hashtable to be initialized - * - * Calculates the size of the hashtable from the given parameter, otherwise - * same as hash_init_size. - * - * This has to be a macro since CCO_HASH_BITS() will not work on pointers since - * it calculates the size during preprocessing. - */ -static inline void __cco_hash_init(struct cco_hlist *ht, unsigned sz) -{ - for (unsigned i = 0; i < sz; i++) - CCO_HLIST_INIT(&ht[i]); -} - -#define cco_hash_init(ht) __cco_hash_init(ht, CCO_HASH_SIZE(ht)) - -/** - * cco_hash_add - add an object to a hashtable - * @ht: hashtable to add to - * @node: the &struct hnode of the object to be added - * @key: the key of the object to be added - */ -#define cco_hash_add(ht, node, key) \ - __cco_hlist_add(node, &ht[cco_hash_min(key, CCO_HASH_BITS(ht))]) - -static inline bool __cco_hash_empty(struct cco_hlist *ht, unsigned sz) -{ - for (unsigned i = 0; i < sz; i++) - if (!cco_hlist_empty(&ht[i])) return false; - - return true; -} - -/** - * cco_hash_empty - check whether a hashtable is empty - * @ht: hashtable to check - * - * This has to be a macro since CCO_HASH_BITS() will not work on pointers since - * it calculates the size during preprocessing. - */ -#define cco_hash_empty(ht) __cco_hash_empty(ht, CCO_HASH_SIZE(ht)) - -/** - * cco_hash_del - remove an object from a hashtable - * @node: &struct hnode of the object to remove - */ -static inline void cco_hash_del(struct cco_hnode *node) -{ - cco_hnode_del_init(node); -} - -/** - * cco_hash_hashed - check whether an object is in any hashtable - * @node: the &struct hlist_node of the object to be checked - */ -static inline bool cco_hash_hashed(struct cco_hnode const *node) -{ - return !cco_hlist_unhashed(node); -} - -/** - * cco_hash_for_each_safe - iterate over a hashtable safe against removal of - * hash entry - * @name: hashtable to iterate - * @bkt: integer to use as bucket loop cursor - * @tmp: a &struct hnode used for temporary storage - * @obj: the type * to use as a loop cursor for each entry - * @member: the name of the hnode within the struct - */ -#define cco_hash_for_each_safe(name, bkt, tmp, obj, member) \ - for ((bkt) = 0, obj = NULL; obj == NULL && (bkt) < CCO_HASH_SIZE(name); \ - (bkt)++) \ - __cco_hlist_for_each_entry_safe(obj, tmp, &name[bkt], member) - -/** - * cco_hash_for_each_possible - iterate over all possible objects hashing to the - * same bucket - * @name: hashtable to iterate - * @obj: the type * to use as a loop cursor for each entry - * @member: the name of the hnode within the struct - * @key: the key of the objects to iterate over - */ -#define cco_hash_for_each_possible(name, obj, member, key) \ - __cco_hlist_for_each_entry( \ - obj, &name[cco_hash_min(key, CCO_HASH_BITS(name))], member) - -/** - * cco_hash_for_each_possible_safe - iterate over all possible objects hashing - * to the same bucket safe against removals - * @name: hashtable to iterate - * @obj: the type * to use as a loop cursor for each entry - * @tmp: a &struct hnode used for temporary storage - * @member: the name of the hnode within the struct - * @key: the key of the objects to iterate over - */ -#define cco_hash_for_each_possible_safe(name, obj, tmp, member, key) \ - __cco_hlist_for_each_entry_safe( \ - obj, tmp, &name[cco_hash_min(key, CCO_HASH_BITS(name))], member) - -/** - * cco_hash_for_each - iterate over a hashtable - * @name: hashtable to iterate - * @bkt: integer to use as bucket loop cursor - * @obj: the type * to use as a loop cursor for each entry - * @member: the name of the hnode within the struct - */ -#define cco_hash_for_each(name, bkt, obj, member) \ - for ((bkt) = 0, obj = NULL; obj == NULL && (bkt) < CCO_HASH_SIZE(name); \ - (bkt)++) \ - __cco_hlist_for_each_entry(obj, &name[bkt], member) -/* ---- cco_hash module end ------------------------------------------------- */ - -/* ---- cco_iter module begin ----------------------------------------------- */ -struct cco_iter -{ - struct cco_node *curr; - struct cco_node const *end; -}; - -static inline struct cco_node *cco_iter_next(struct cco_iter *iter) -{ - if (!iter || iter->curr == iter->end) return NULL; - struct cco_node *node = iter->curr; - iter->curr = node->next; - return node; -} - -#define cco_iter_entry(pos, type, member) cco_of_safe(pos, type, member) - -#define cco_iter_next_entry(iter, entry, member) \ - cco_of_safe(cco_iter_next(iter), __typeof__(*entry), member) - -#define cco_iter_for_each(pos, iter, member) \ - for (pos = cco_iter_next(iter); pos; pos = cco_iter_next(iter)) - -#define cco_iter_for_each_safe(pos, tmp, iter, member) \ - for (pos = cco_iter_next(iter), tmp = cco_iter_next(iter); pos; \ - pos = tmp, tmp = iter_next(iter)) - -#define cco_iter_for_each_entry(entry, iter, member) \ - for (entry = cco_iter_next_entry(iter, entry, member); entry; \ - entry = cco_iter_next_entry(iter, entry, member)) - -#define cco_iter_for_each_entry_safe(entry, tmp, iter, member) \ - for (entry = cco_iter_next_entry(iter, entry, member), \ - tmp = cco_iter_next_entry(iter, entry, member); \ - entry; entry = tmp, tmp = cco_iter_next_entry(iter, entry, member)) -/* ---- cco_iter module end ------------------------------------------------- */ - -/* ---- cco_queue module begin ---------------------------------------------- */ -#include - -struct cco_queue -{ - struct cco_node head; - struct cco_node *tail; -}; - -#define CCO_QUEUE_INIT(name) \ - { \ - (struct cco_node){&name.head}, &name.head \ - } - -static inline bool cco_queue_empty(struct cco_queue const *queue) -{ - return &queue->head == queue->tail; -} - -static inline void cco_queue_init(struct cco_queue *queue) -{ - queue->tail = queue->head.next = &queue->head; -} - -static inline struct cco_iter cco_queue_iter(struct cco_queue *queue) -{ - return (struct cco_iter){queue->tail, &queue->head}; -} - -static inline struct cco_node *cco_queue_pop(struct cco_queue *queue) -{ - struct cco_node *node = queue->tail; - queue->tail = queue->tail->next; - if (queue->tail == &queue->head) queue->head.next = &queue->head; - return node; -} - -static inline void cco_queue_put(struct cco_queue *queue, - struct cco_node *novel) -{ - if (cco_queue_empty(queue)) queue->tail = novel; - - struct cco_node *next = queue->head.next; - next->next = novel; - novel->next = &queue->head; - queue->head.next = novel; -} - -static inline void cco_queue_put_first(struct cco_queue *queue, - struct cco_node *novel) -{ - struct cco_node *tail = queue->tail; - novel->next = tail; - queue->tail = novel; - if (queue->head.next == &queue->head) queue->head.next = novel; -} -/* ---- cco_queue module end ------------------------------------------------ */ - -/* ---- cco_stack module begin ---------------------------------------------- */ -#include - -struct cco_stack -{ - struct cco_node head; -}; - -#define CCO_STACK_INIT() \ - { \ - CCO_NODE_INIT() \ - } - -static inline bool cco_stack_empty(struct cco_stack const *stack) -{ - return stack->head.next == NULL; -} - -static inline void cco_stack_init(struct cco_stack *stack) -{ - cco_node_init(&stack->head); -} - -static inline struct cco_iter cco_stack_iter(struct cco_stack *stack) -{ - return (struct cco_iter){stack->head.next, NULL}; -} - -static inline struct cco_node *cco_stack_pop(struct cco_stack *stack) -{ - struct cco_node *node = stack->head.next; - cco_node_del(&stack->head, node); - return node; -} - -static inline void cco_stack_put(struct cco_stack *stack, - struct cco_node *novel) -{ - cco_node_add_next(&stack->head, novel); -} -/* ---- cco_stack module end ------------------------------------------------ */ - -#endif diff --git a/h3client/compiler.h b/h3client/compiler.h deleted file mode 100644 index b15067c..0000000 --- a/h3client/compiler.h +++ /dev/null @@ -1,13 +0,0 @@ -#ifndef COMPILER_H -#define COMPILER_H - -#include - -#ifndef static_assert -#define static_assert(expr, msg) _Static_assert(expr, msg) -#endif - -#define STATIC_ASSERT(test_for_true) \ - static_assert((test_for_true), "(" #test_for_true ") failed") - -#endif diff --git a/h3client/copy_string.h b/h3client/copy_string.h deleted file mode 100644 index 1e830e9..0000000 --- a/h3client/copy_string.h +++ /dev/null @@ -1,18 +0,0 @@ -#ifndef COPY_STRING -#define COPY_STRING - -#include -#include -#include - -static int copy_string(size_t size, char dst[size], char const src[static 1]) -{ - if (size == 0) return 1; - size_t count = strlen(src); - if (count >= size) return 1; - memcpy(dst, src, count); - dst[count] = '\0'; - return 0; -} - -#endif diff --git a/h3client/discard.h b/h3client/discard.h new file mode 100644 index 0000000..60cb9cf --- /dev/null +++ b/h3client/discard.h @@ -0,0 +1,12 @@ +#ifndef DISCARD_H +#define DISCARD_H + +#include "full_recv.h" + +static inline int discard(int fd, size_t size) +{ + unsigned char buffer[128] = {0}; + return full_recv(fd, size, buffer); +} + +#endif diff --git a/h3client/echo.c b/h3client/echo.c deleted file mode 100644 index 9fd719a..0000000 --- a/h3client/echo.c +++ /dev/null @@ -1,11 +0,0 @@ -#include "echo.h" -#include - -void h3client_echo(FILE *stream, char const *fmt, ...) -{ - va_list params = {0}; - va_start(params, fmt); - vfprintf(stream, fmt, params); - fputc('\n', stream); - va_end(params); -} diff --git a/h3client/echo.h b/h3client/echo.h deleted file mode 100644 index 233df8e..0000000 --- a/h3client/echo.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef ECHO_H -#define ECHO_H - -#include - -void h3client_echo(FILE *stream, char const *fmt, ...); - -#endif diff --git a/h3client/fs.c b/h3client/fs.c deleted file mode 100644 index 3a85e82..0000000 --- a/h3client/fs.c +++ /dev/null @@ -1,596 +0,0 @@ -#if !defined(_POSIX_C_SOURCE) || _POSIX_C_SOURCE < 200809L -#undef _POSIX_C_SOURCE -#define _POSIX_C_SOURCE 200809L -#endif - -#if !defined(_FILE_OFFSET_BITS) || _FILE_OFFSET_BITS < 64 -#undef _FILE_OFFSET_BITS -#define _FILE_OFFSET_BITS 64 -#endif - -#include "fs.h" -#include -#include -#include -#include -#include -#include -#include - -#ifdef __APPLE__ -#ifdef _DARWIN_C_SOURCE -#undef _DARWIN_C_SOURCE -#endif -#define _DARWIN_C_SOURCE 1 -#include -#include -#endif - -#if defined(__APPLE__) || defined(__FreeBSD__) -#include -#else -#include -#include -#endif - -#define BUFFSIZE (8 * 1024) -#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0])) -#define LINESIZE BUFFSIZE - -static char *error_strings[] = { -#define X(_, A) A, - FS_MAP(X) -#undef X -}; - -int fs_size(char const *filepath, long *size) -{ - struct stat st = {0}; - if (stat(filepath, &st) == 1) return FS_ESTAT; - *size = (long)st.st_size; - return FS_OK; -} - -int fs_size_fp(FILE *fp, long *size) -{ - off_t old = ftello(fp); - if (old < 0) return FS_EFTELL; - - if (fseeko(fp, 0, SEEK_END) < 0) return FS_EFSEEK; - - *size = ftello(fp); - if (*size < 0) return FS_EFSEEK; - - if (fseeko(fp, old, SEEK_SET) < 0) return FS_EFSEEK; - - return FS_OK; -} - -int fs_size_fd(int fd, long *size) -{ - struct stat st = {0}; - if (fsync(fd) < 0) return FS_EFSYNC; - if (fstat(fd, &st) < 0) return FS_EFSTAT; - *size = st.st_size; - return FS_OK; -} - -int fs_getperm(char const *path, int who, int perm, bool *value) -{ - struct stat st; - if (stat(path, &st)) return FS_ESTAT; - - if (who == FS_OWNER && perm == FS_READ) - *value = st.st_mode & S_IRUSR; - else if (who == FS_OWNER && perm == FS_WRITE) - *value = st.st_mode & S_IWUSR; - else if (who == FS_OWNER && perm == FS_EXEC) - *value = st.st_mode & S_IXUSR; - else if (who == FS_GROUP && perm == FS_READ) - *value = st.st_mode & S_IRGRP; - else if (who == FS_GROUP && perm == FS_WRITE) - *value = st.st_mode & S_IWGRP; - else if (who == FS_GROUP && perm == FS_EXEC) - *value = st.st_mode & S_IXGRP; - else if (who == FS_ALL && perm == FS_READ) - *value = st.st_mode & S_IROTH; - else if (who == FS_ALL && perm == FS_WRITE) - *value = st.st_mode & S_IWOTH; - else if (who == FS_ALL && perm == FS_EXEC) - *value = st.st_mode & S_IXOTH; - - return FS_EINVAL; -} - -int fs_setperm(char const *path, int who, int perm, bool value) -{ - struct stat st; - if (stat(path, &st)) return FS_ESTAT; - - if (who == FS_OWNER && perm == FS_READ) - st.st_mode = (st.st_mode & ~S_IRUSR) | (value ? S_IRUSR : 0); - else if (who == FS_OWNER && perm == FS_WRITE) - st.st_mode = (st.st_mode & ~S_IWUSR) | (value ? S_IWUSR : 0); - else if (who == FS_OWNER && perm == FS_EXEC) - st.st_mode = (st.st_mode & ~S_IXUSR) | (value ? S_IXUSR : 0); - else if (who == FS_GROUP && perm == FS_READ) - st.st_mode = (st.st_mode & ~S_IRGRP) | (value ? S_IRGRP : 0); - else if (who == FS_GROUP && perm == FS_WRITE) - st.st_mode = (st.st_mode & ~S_IWGRP) | (value ? S_IWGRP : 0); - else if (who == FS_GROUP && perm == FS_EXEC) - st.st_mode = (st.st_mode & ~S_IXGRP) | (value ? S_IXGRP : 0); - else if (who == FS_ALL && perm == FS_READ) - st.st_mode = (st.st_mode & ~S_IROTH) | (value ? S_IROTH : 0); - else if (who == FS_ALL && perm == FS_WRITE) - st.st_mode = (st.st_mode & ~S_IWOTH) | (value ? S_IWOTH : 0); - else if (who == FS_ALL && perm == FS_EXEC) - st.st_mode = (st.st_mode & ~S_IXOTH) | (value ? S_IXOTH : 0); - else - return FS_EINVAL; - - return chmod(path, st.st_mode) ? FS_ECHMOD : FS_OK; -} - -int fs_tell(FILE *restrict fp, long *offset) -{ - return (*offset = ftello(fp)) < 0 ? FS_EFTELL : FS_OK; -} - -int fs_seek(FILE *restrict fp, long offset, int whence) -{ - return fseeko(fp, (off_t)offset, whence) < 0 ? FS_EFSEEK : FS_OK; -} - -int fs_copy(char const *dst, char const *src) -{ - int input = 0; - int output = 0; - - if ((input = open(src, O_RDONLY)) == -1) - { - return FS_EOPEN; - } - if ((output = creat(dst, 0660)) == -1) - { - close(input); - return FS_ECREAT; - } - - // Here we use kernel-space copying for performance reasons -#if defined(__APPLE__) || defined(__FreeBSD__) - // fcopyfile works on FreeBSD and OS X 10.5+ - if (fcopyfile(input, output, 0, COPYFILE_ALL)) - { - close(input); - close(output); - return FS_EFCOPYFILE; - } -#else - // sendfile will work with non-socket output (i.e. regular file) on - // Linux 2.6.33+ - long size = 0; - int rc = fs_size_fd(input, &size); - if (rc) - { - close(input); - close(output); - return rc; - } - off_t offset = 0; - ssize_t cnt = (ssize_t)size; - if (sendfile(output, input, &offset, cnt) != cnt) - { - close(input); - close(output); - return FS_ESENDFILE; - } -#endif - - if (close(input)) - { - close(output); - return FS_ECLOSE; - } - return close(output) ? FS_ECLOSE : FS_OK; -} - -int fs_copy_fp(FILE *restrict dst, FILE *restrict src) -{ - static _Thread_local char buffer[BUFFSIZE]; - size_t n = 0; - while ((n = fread(buffer, sizeof(*buffer), BUFFSIZE, src)) > 0) - { - if (n < BUFFSIZE && ferror(src)) return FS_EFREAD; - - if (fwrite(buffer, sizeof(*buffer), n, dst) < n) return FS_EFWRITE; - } - if (ferror(src)) return FS_EFREAD; - - return FS_OK; -} - -int fs_unlink(char const *filepath) -{ - return unlink(filepath) < 0 ? FS_EUNLINK : FS_OK; -} - -int fs_rmdir(char const *dirpath) -{ - return rmdir(dirpath) < 0 ? FS_ERMDIR : FS_OK; -} - -static int concat_path_file(unsigned size, char *dst, const char *path, - const char *filename); - -int fs_mkstemp(unsigned size, char *filepath) -{ - filepath[0] = '\0'; - static char const template[] = "tmp.XXXXXXXXXX"; - char const *tmpdir = getenv("TMPDIR"); - if (!tmpdir || tmpdir[0] == '\0') tmpdir = "/tmp"; - int rc = concat_path_file(size, filepath, tmpdir, template); - if (rc) return rc; - return mkstemp(filepath) < 0 ? FS_EMKSTEMP : FS_OK; -} - -int fs_move(char const *restrict dst, char const *restrict src) -{ - if (rename(src, dst) == 0) return FS_OK; - FILE *fdst = fopen(dst, "wb"); - if (!fdst) return FS_EFOPEN; - - FILE *fsrc = fopen(src, "rb"); - if (!fsrc) - { - fclose(fdst); - return FS_EFOPEN; - } - - int rc = fs_copy_fp(fdst, fsrc); - if (!fclose(fdst) && fclose(fsrc)) fs_unlink(src); - return rc; -} - -int fs_refopen(FILE *fp, char const *mode, FILE **out) -{ - char filepath[FILENAME_MAX] = {0}; - int rc = fs_getpath(fp, sizeof filepath, filepath); - if (rc) return rc; - return (*out = fopen(filepath, mode)) ? FS_OK : FS_EFOPEN; -} - -int fs_fileno(FILE *fp, int *fd) -{ - return (*fd = fileno(fp)) < 0 ? FS_EFILENO : FS_OK; -} - -int fs_getpath(FILE *fp, unsigned size, char *filepath) -{ - int fd = 0; - int rc = fs_fileno(fp, &fd); - if (rc) return rc; - -#ifdef __APPLE__ - (void)size; - char pathbuf[MAXPATHLEN] = {0}; - if (fcntl(fd, F_GETPATH, pathbuf) < 0) return FS_EFCNTL; - if (strlen(pathbuf) >= size) return FS_ETRUNCPATH; - strcpy(filepath, pathbuf); -#else - char pathbuf[FILENAME_MAX] = {0}; - sprintf(pathbuf, "/proc/self/fd/%d", fd); - ssize_t n = readlink(pathbuf, filepath, size); - if (n < 0) return FS_EREADLINK; - if (n >= size) return FS_ETRUNCPATH; - filepath[n] = '\0'; -#endif - - return FS_OK; -} - -bool fs_exists(char const *filepath) { return access(filepath, F_OK) == 0; } - -int fs_touch(char const *filepath) -{ - if (fs_exists(filepath)) return FS_OK; - FILE *fp = fopen(filepath, "wb"); - if (!fp) return FS_EFOPEN; - return fclose(fp) ? FS_EFCLOSE : FS_OK; -} - -int fs_readall(char const *filepath, long *size, unsigned char **data) -{ - *size = 0; - *data = NULL; - int rc = fs_size(filepath, size); - if (rc) return rc; - - if (*size == 0) return 0; - - FILE *fp = fopen(filepath, "rb"); - if (!fp) return FS_EFOPEN; - - if (!(*data = malloc(*size))) - { - fclose(fp); - return FS_ENOMEM; - } - - if (fread(*data, *size, 1, fp) < 1) - { - fclose(fp); - free(*data); - return FS_EFREAD; - } - - return fclose(fp) ? FS_EFCLOSE : FS_OK; -} - -int fs_writeall(char const *filepath, long size, unsigned char *data) -{ - FILE *fp = fopen(filepath, "wb"); - if (!fp) return FS_EFOPEN; - - if (size <= 0) return fclose(fp) ? FS_EFCLOSE : FS_OK; - - if (fwrite(data, size, 1, fp) < 1) - { - fclose(fp); - return FS_EFWRITE; - } - - return fclose(fp) ? FS_EFCLOSE : FS_OK; -} - -char const *fs_strerror(int rc) -{ - if (rc < 0 || rc >= (int)ARRAY_SIZE(error_strings)) return "unknown error"; - return error_strings[rc]; -} - -int fs_join(FILE *a, FILE *b, FILE *out) -{ - static _Thread_local char line[LINESIZE] = {0}; - - while (fgets(line, sizeof(line), a)) - { - if (ferror(a)) return FS_EFGETS; - if (fwrite(line, sizeof(*line), strlen(line), out) < 1) return FS_EFWRITE; - } - if (ferror(a)) return FS_EFGETS; - - while (fgets(line, sizeof(line), b)) - { - if (ferror(b)) return FS_EFGETS; - if (fwrite(line, sizeof(*line), strlen(line), out) < 1) return FS_EFWRITE; - } - return ferror(b) ? FS_EFGETS : FS_OK; -} - -int fs_split(FILE *in, long cut, FILE *a, FILE *b) -{ - static _Thread_local char line[LINESIZE] = {0}; - - long i = 0; - while (fgets(line, sizeof(line), in)) - { - if (ferror(in)) return FS_EFGETS; - if (i < cut) - { - if (fwrite(line, sizeof(*line), strlen(line), a) < 1) return FS_EFWRITE; - } - else if (fwrite(line, sizeof(*line), strlen(line), b) < 1) - return FS_EFWRITE; - ++i; - } - return ferror(in) ? FS_EFGETS : FS_OK; -} - -static char *_fs_strdup(char const *str); - -static void _fs_readlines_cleanup(long cnt, char *lines[]) -{ - for (long i = 0; i < cnt; ++i) - free(lines[i]); - free(lines); -} - -int fs_readlines(char const *filepath, long *cnt, char **lines[]) -{ - static _Thread_local char line[LINESIZE] = {0}; - - FILE *fp = fopen(filepath, "r"); - if (!fp) return FS_EFOPEN; - - *cnt = 0; - *lines = NULL; - - while (fgets(line, sizeof(line), fp)) - { - if (ferror(fp)) return FS_EFGETS; - - char **ptr = NULL; - if (*cnt == 0) - { - ptr = malloc((*cnt + 1) * sizeof(*lines)); - if (!ptr) return FS_ENOMEM; - } - else - { - ptr = realloc(*lines, (*cnt + 1) * sizeof(*lines)); - if (!ptr) - { - _fs_readlines_cleanup(*cnt, *lines); - return FS_ENOMEM; - } - } - char *str = _fs_strdup(line); - if (!str) - { - _fs_readlines_cleanup(*cnt, *lines); - return FS_ENOMEM; - } - *lines = ptr; - (*lines)[*cnt] = str; - *cnt += 1; - } - return ferror(fp) ? FS_EFGETS : FS_OK; -} - -int fs_writelines(char const *filepath, long cnt, char *lines[]) -{ - FILE *fp = fopen(filepath, "w"); - if (!fp) return FS_EFOPEN; - - if (cnt <= 0) return fclose(fp) ? FS_EFCLOSE : FS_OK; - - for (long i = 0; i < cnt; ++i) - { - if (fputs(lines[i], fp) < 1) - { - fclose(fp); - return FS_EFWRITE; - } - size_t n = strlen(lines[i]); - if (n == 0 || lines[i][n - 1] != '\n') - { - if (fputc('\n', fp) != '\n') - { - fclose(fp); - return FS_EFPUTC; - } - } - } - - return fclose(fp) ? FS_EFCLOSE : FS_OK; -} - -int fs_ljoin(FILE *left, FILE *right) -{ - FILE *tmp = tmpfile(); - if (!tmp) return FS_ETMPFILE; - - rewind(left); - int rc = fs_copy_fp(tmp, left); - if (rc) goto cleanup; - - rewind(tmp); - rewind(left); - rewind(right); - rc = fs_join(tmp, right, left); - -cleanup: - fclose(tmp); - return rc; -} - -int fs_rjoin(FILE *left, FILE *right) -{ - FILE *tmp = tmpfile(); - if (!tmp) return FS_ETMPFILE; - - rewind(right); - int rc = fs_copy_fp(tmp, right); - if (rc) goto cleanup; - - rewind(tmp); - rewind(left); - rewind(right); - rc = fs_join(left, tmp, right); - -cleanup: - fclose(tmp); - return rc; -} - -static int compare(const void *a, const void *b) -{ - return strcmp(*((char const **)a), *((char const **)b)); -} - -int fs_sort(char const *filepath) -{ - long cnt = 0; - char **lines = NULL; - int rc = FS_OK; - - if ((rc = fs_readlines(filepath, &cnt, &lines))) return rc; - qsort(lines, cnt, sizeof(*lines), &compare); - rc = fs_writelines(filepath, cnt, lines); - - _fs_readlines_cleanup(cnt, lines); - return rc; -} - -static int _fs_fletcher16(FILE *fp, uint8_t *buf, size_t bufsize, long *chk) -{ - size_t n = 0; - uint16_t sum1 = 0; - uint16_t sum2 = 0; - while ((n = fread(buf, 1, bufsize, fp)) > 0) - { - if (n < bufsize && ferror(fp)) return FS_EFREAD; - for (int i = 0; i < (int)n; ++i) - { - sum1 = (sum1 + buf[i]) % 255; - sum2 = (sum2 + sum1) % 255; - } - } - if (ferror(fp)) return FS_EFREAD; - - *chk = (sum2 << 8) | sum1; - return FS_OK; -} - -int fs_cksum(char const *filepath, int algo, long *chk) -{ - static _Thread_local uint8_t buffer[BUFFSIZE]; - FILE *fp = fopen(filepath, "rb"); - if (!fp) return FS_EFOPEN; - - int rc = 0; - if (algo == FS_FLETCHER16) - rc = _fs_fletcher16(fp, buffer, sizeof(buffer), chk); - else - rc = FS_EINVAL; - - fclose(fp); - return rc; -} - -// ACK: BusyBox -static char *last_char_is(const char *s, int c) -{ - if (!s[0]) return NULL; - while (s[1]) - s++; - return (*s == (char)c) ? (char *)s : NULL; -} - -// ACK: BusyBox -static int concat_path_file(unsigned size, char *dst, const char *path, - const char *filename) -{ - if (!path) path = ""; - char *lc = last_char_is(path, '/'); - while (*filename == '/') - filename++; - - char const *sep = lc == NULL ? "/" : ""; - if (strlen(path) + strlen(sep) + strlen(filename) >= size) - return FS_ETRUNCPATH; - - dst[0] = '\0'; - strcat(strcat(strcat(dst, path), sep), filename); - return FS_OK; -} - -static char *_fs_strdup(char const *str) -{ - size_t len = strlen(str) + 1; - void *new = malloc(len); - - if (new == NULL) return NULL; - - return (char *)memcpy(new, str, len); -} diff --git a/h3client/fs.h b/h3client/fs.h deleted file mode 100644 index a2d6682..0000000 --- a/h3client/fs.h +++ /dev/null @@ -1,104 +0,0 @@ -#ifndef FS_H -#define FS_H - -#include -#include -#include - -#define FS_MAP(X) \ - X(OK, "not an error") \ - X(ECHMOD, "chmod failed") \ - X(ECLOSE, "close failed") \ - X(ECREAT, "creat failed") \ - X(EFCLOSE, "fclose failed") \ - X(EFCNTL, "fcntl failed") \ - X(EFCOPYFILE, "fcopyfile failed") \ - X(EFGETS, "fgets failed") \ - X(EFILENO, "fileno failed") \ - X(EFOPEN, "fopen failed") \ - X(EFPUTC, "fputc failed") \ - X(EFREAD, "fread failed") \ - X(EFSEEK, "fseek failed") \ - X(EFSTAT, "fstat failed") \ - X(EFSYNC, "fsync failed") \ - X(EFTELL, "ftell failed") \ - X(EFWRITE, "fwrite failed") \ - X(EINVAL, "invalid value") \ - X(EMKSTEMP, "mkstemp failed") \ - X(ENOMEM, "not enough memory") \ - X(EOPEN, "open failed") \ - X(EREADLINK, "readlink failed") \ - X(ERMDIR, "rmdir failed") \ - X(ESENDFILE, "sendfile failed") \ - X(ESTAT, "stat failed") \ - X(ETMPFILE, "tmpfile failed") \ - X(ETRUNCPATH, "truncated path") \ - X(EUNLINK, "unlink failed") - -enum fs_rc -{ -#define X(A, _) FS_##A, - FS_MAP(X) -#undef X -}; - -enum fs_who -{ - FS_OWNER, - FS_GROUP, - FS_ALL, -}; - -enum fs_perm -{ - FS_READ, - FS_WRITE, - FS_EXEC, -}; - -enum fs_algo -{ - FS_FLETCHER16, -}; - -int fs_size(char const *filepath, long *size); -int fs_size_fp(FILE *fp, long *size); -int fs_size_fd(int fd, long *size); - -int fs_getperm(char const *path, int who, int perm, bool *value); -int fs_setperm(char const *path, int who, int perm, bool value); - -int fs_tell(FILE *restrict fp, long *offset); -int fs_seek(FILE *restrict fp, long offset, int whence); - -int fs_copy(char const *dst, char const *src); -int fs_copy_fp(FILE *restrict dst, FILE *restrict src); -int fs_unlink(char const *filepath); -int fs_rmdir(char const *dirpath); -int fs_mkstemp(unsigned size, char *filepath); -int fs_move(char const *restrict dst, char const *restrict src); - -int fs_refopen(FILE *fp, char const *mode, FILE **out); -int fs_fileno(FILE *fp, int *fd); -int fs_getpath(FILE *fp, unsigned size, char *filepath); - -bool fs_exists(char const *filepath); -int fs_touch(char const *filepath); - -int fs_readall(char const *filepath, long *size, unsigned char **data); -int fs_writeall(char const *filepath, long size, unsigned char *data); - -char const *fs_strerror(int rc); - -int fs_join(FILE *a, FILE *b, FILE *out); -int fs_split(FILE *in, long cut, FILE *a, FILE *b); -int fs_readlines(char const *filepath, long *cnt, char **lines[]); -int fs_writelines(char const *filepath, long cnt, char *lines[]); - -int fs_ljoin(FILE *left, FILE *right); -int fs_rjoin(FILE *left, FILE *right); - -int fs_sort(char const *filepath); -int fs_cksum(char const *filepath, int algo, long *chk); - -#endif diff --git a/h3client/full_recv.h b/h3client/full_recv.h new file mode 100644 index 0000000..37beb28 --- /dev/null +++ b/h3client/full_recv.h @@ -0,0 +1,18 @@ +#ifndef FULL_RECV_H +#define FULL_RECV_H + +#include + +static inline int full_recv(int fd, size_t size, unsigned char *buffer) +{ + while (size > 0) + { + ssize_t n = recv(fd, buffer, size, 0); + if (n == -1 || n == 0) return 1; + buffer += n; + size -= (size_t)n; + } + return 0; +} + +#endif diff --git a/h3client/full_send.h b/h3client/full_send.h new file mode 100644 index 0000000..636f28e --- /dev/null +++ b/h3client/full_send.h @@ -0,0 +1,18 @@ +#ifndef FULL_SEND_H +#define FULL_SEND_H + +#include + +static inline int full_send(int fd, size_t size, unsigned char const *buffer) +{ + while (size > 0) + { + ssize_t n = send(fd, buffer, size, 0); + if (n == -1) return 1; + buffer += n; + size -= (size_t)n; + } + return 0; +} + +#endif diff --git a/h3client/h3c_clock.c b/h3client/h3c_clock.c new file mode 100644 index 0000000..a42fd4a --- /dev/null +++ b/h3client/h3c_clock.c @@ -0,0 +1,37 @@ +#include "h3c_clock.h" +#include +#include +#include +#include +#include +#include + +// Explanation: +// https://github.com/nanomsg/nng/blob/a8a8bd435690e24e55dcdad485e97225902cb0c8/src/platform/posix/posix_config.h#L25 +#ifndef USE_CLOCKID +#if defined(__APPLE__) +#define USE_CLOCKID CLOCK_REALTIME +#elif defined(CLOCK_MONOTONIC) +#define USE_CLOCKID CLOCK_MONOTONIC +#elif defined(CLOCK_REALTIME) +#define USE_CLOCKID CLOCK_REALTIME +#else +#error "Could not set clock id." +#endif +#endif + +long h3c_clock(void) +{ + struct timespec ts = {0}; + + if (clock_gettime(USE_CLOCKID, &ts) != 0) + { + fprintf(stderr, "clock_gettime failed: %s", strerror(errno)); + abort(); + } + + long msec = ts.tv_sec; + msec *= 1000; + msec += (ts.tv_nsec / 1000000); + return msec; +} diff --git a/h3client/h3c_clock.h b/h3client/h3c_clock.h new file mode 100644 index 0000000..83613a2 --- /dev/null +++ b/h3client/h3c_clock.h @@ -0,0 +1,6 @@ +#ifndef H3C_CLOCK_H +#define H3C_CLOCK_H + +long h3c_clock(void); + +#endif diff --git a/h3client/h3c_deadline.c b/h3client/h3c_deadline.c deleted file mode 100644 index 3515155..0000000 --- a/h3client/h3c_deadline.c +++ /dev/null @@ -1,5 +0,0 @@ -#include "h3c_deadline.h" -#include "nng/nng.h" -#include "nng/supplemental/util/platform.h" - -long h3client_deadline(long timeout) { return (long)nng_clock() + timeout; } diff --git a/h3client/h3c_deadline.h b/h3client/h3c_deadline.h deleted file mode 100644 index 0003375..0000000 --- a/h3client/h3c_deadline.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef H3C_DEADLINE_H -#define H3C_DEADLINE_H - -long h3client_deadline(long timeout); - -#endif diff --git a/h3client/h3c_dialer.c b/h3client/h3c_dialer.c deleted file mode 100644 index 7072638..0000000 --- a/h3client/h3c_dialer.c +++ /dev/null @@ -1,90 +0,0 @@ -#include "h3c_dialer.h" -#include "h3c_errno.h" -#include "h3c_stream.h" -#include "itoa.h" -#include "nng/nng.h" -#include "nnge.h" -#include "timeout.h" -#include -#include - -struct h3client_dialer -{ - nng_stream_dialer *stream; - nng_aio *aio; - struct h3client_stream *h3client_stream; -}; - -struct h3client_dialer *h3client_dialer_new(char const *ip, int port) -{ - struct h3client_dialer *dialer = malloc(sizeof(*dialer)); - if (!dialer) return NULL; - - char uri[512] = "tcp://"; - strncat(uri, ip, sizeof(uri) - strlen(uri) - 27); - strcat(uri, ":"); - h3client_itoa(uri + strlen(uri), port); - - dialer->stream = NULL; - dialer->aio = NULL; - dialer->h3client_stream = NULL; - - if (nng_stream_dialer_alloc(&dialer->stream, uri)) - { - free(dialer); - return NULL; - } - - if (nng_aio_alloc(&dialer->aio, NULL, NULL)) - { - nng_stream_dialer_close(dialer->stream); - nng_stream_dialer_free(dialer->stream); - free(dialer); - return NULL; - } - - return dialer; -} - -int h3client_dialer_dial(struct h3client_dialer *x, long deadline) -{ - nng_aio_set_timeout(x->aio, h3client_timeout(deadline)); - nng_stream_dialer_dial(x->stream, x->aio); - nng_aio_wait(x->aio); - - int rc = h3client_nnge(nng_aio_result(x->aio)); - if (rc) return rc; - - struct nng_stream *s = nng_aio_get_output(x->aio, 0); - struct h3client_stream *stream = h3client_stream_new(s); - if (!stream) - { - nng_stream_close(s); - nng_stream_free(s); - return H3C_ENOMEM; - } - x->h3client_stream = stream; - return 0; -} - -struct h3client_stream *h3client_dialer_stream(struct h3client_dialer *x) -{ - struct h3client_stream *s = x->h3client_stream; - x->h3client_stream = NULL; - return s; -} - -void h3client_dialer_del(struct h3client_dialer *x) -{ - if (!x) return; - - if (x->h3client_stream) h3client_stream_del(x->h3client_stream); - if (x->aio) nng_aio_free(x->aio); - if (x->stream) - { - nng_stream_dialer_close(x->stream); - nng_stream_dialer_free(x->stream); - } - - free(x); -} diff --git a/h3client/h3c_dialer.h b/h3client/h3c_dialer.h deleted file mode 100644 index f26a425..0000000 --- a/h3client/h3c_dialer.h +++ /dev/null @@ -1,12 +0,0 @@ -#ifndef H3C_DIALER_H -#define H3C_DIALER_H - -struct h3client_dialer; -struct h3client_stream; - -struct h3client_dialer *h3client_dialer_new(char const *ip, int port); -int h3client_dialer_dial(struct h3client_dialer *, long deadline); -struct h3client_stream *h3client_dialer_stream(struct h3client_dialer *x); -void h3client_dialer_del(struct h3client_dialer *); - -#endif diff --git a/h3client/h3c_errno.h b/h3client/h3c_errnum.h similarity index 68% rename from h3client/h3c_errno.h rename to h3client/h3c_errnum.h index 8a50e86..cdb770d 100644 --- a/h3client/h3c_errno.h +++ b/h3client/h3c_errnum.h @@ -1,8 +1,7 @@ -#ifndef H3C_ERRNO_H -#define H3C_ERRNO_H +#ifndef H3C_ERRNUM_H +#define H3C_ERRNUM_H -// clang-format off -enum h3client_errno +enum h3client_errnum { H3C_EUNKNOWN = 1, H3C_EPARSE = 2, @@ -22,7 +21,12 @@ enum h3client_errno H3C_EPROTO = 16, H3C_EUNREACHABLE = 17, H3C_ECONNSHUT = 18, + H3C_EDISCARD = 19, + H3C_EWARMUPCODE = 20, + H3C_EH3DAEMON = 21, + H3C_ERECV = 22, + H3C_ESEND = 23, + H3C_EH3RESULT = 24, }; -// clang-format on #endif diff --git a/h3client/h3c_fini.c b/h3client/h3c_fini.c deleted file mode 100644 index 3fe411b..0000000 --- a/h3client/h3c_fini.c +++ /dev/null @@ -1,4 +0,0 @@ -#include "h3c_fini.h" -#include "nng/nng.h" - -void h3client_fini(void) { nng_fini(); } diff --git a/h3client/h3c_fini.h b/h3client/h3c_fini.h deleted file mode 100644 index c626dc9..0000000 --- a/h3client/h3c_fini.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef H3C_FINI_H -#define H3C_FINI_H - -void h3client_fini(void); - -#endif diff --git a/h3client/h3c_result.c b/h3client/h3c_result.c deleted file mode 100644 index 8ab934d..0000000 --- a/h3client/h3c_result.c +++ /dev/null @@ -1,29 +0,0 @@ -#include "h3c_result.h" -#include "array_size.h" -#include "h3r_result.h" -#include -#include - -struct h3c_result *h3c_result_new(void) -{ - struct h3c_result *x = malloc(sizeof(*x)); - if (!x) return NULL; - - if (!(x->content = h3r_new())) - { - free(x); - return NULL; - } - x->errnum = 0; - memset(x->errstr, '\0', array_size(x->errstr)); - return x; -} - -void h3c_result_del(struct h3c_result const *x) -{ - if (x) - { - h3r_del(x->content); - free((void *)x); - } -} diff --git a/h3client/h3c_result.h b/h3client/h3c_result.h deleted file mode 100644 index b6d8f05..0000000 --- a/h3client/h3c_result.h +++ /dev/null @@ -1,16 +0,0 @@ -#ifndef H3C_RESULT_H -#define H3C_RESULT_H - -#include "h3r_result.h" - -struct h3c_result -{ - struct h3r *content; - int errnum; - char errstr[1024]; -}; - -struct h3c_result *h3c_result_new(void); -void h3c_result_del(struct h3c_result const *); - -#endif diff --git a/h3client/h3c_socket.c b/h3client/h3c_socket.c new file mode 100644 index 0000000..7612870 --- /dev/null +++ b/h3client/h3c_socket.c @@ -0,0 +1,166 @@ +#include "h3c_socket.h" +#include "body.h" +#include "discard.h" +#include "full_recv.h" +#include "full_send.h" +#include "h3c_errnum.h" +#include "head.h" +#include +#include +#include +#include +#include +#include + +#define MIN_BUFFSIZE 0xFFFF + +struct h3c_socket +{ + int fd; + size_t capacity; + unsigned char *buffer; + struct body *body; +}; + +struct h3c_socket *h3c_socket_new(void) +{ + struct h3c_socket *x = malloc(sizeof(struct h3c_socket)); + if (!x) return NULL; + x->capacity = MIN_BUFFSIZE; + if (!(x->buffer = malloc(x->capacity))) + { + free(x); + return NULL; + } + if (!(x->body = body_new())) + { + free(x->buffer); + free(x); + return NULL; + } + return x; +} + +int h3c_socket_dial(struct h3c_socket *x, char const *ip, int port, + long timeout) +{ + if ((x->fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) return 1; + + struct timeval t = {0}; + t.tv_sec = timeout; + t.tv_usec = 0; + + if (setsockopt(x->fd, SOL_SOCKET, SO_SNDTIMEO, &t, sizeof(t)) < 0) + { + perror("Set socket option SO_SNDTIMEO failed"); + close(x->fd); + return 1; + } + + struct sockaddr_in srv_addr = {0}; + srv_addr.sin_family = AF_INET; + srv_addr.sin_port = htons(port); + if (inet_pton(AF_INET, ip, &srv_addr.sin_addr) <= 0) + { + perror("Invalid address or address not supported"); + close(x->fd); + return 1; + } + + if (connect(x->fd, (struct sockaddr *)&srv_addr, sizeof(srv_addr)) < 0) + { + perror("Connection failed"); + close(x->fd); + return EXIT_FAILURE; + } + + return 0; +} + +int h3c_socket_warmup(struct h3c_socket *x) +{ + static unsigned char const warm[] = "@--hmmdb 1 " + "--hmmdb_range " + "0..0 --acc\n>warmup" + "\n\n//"; + if (full_send(x->fd, sizeof(warm) - 1, warm)) return H3C_ESEND; + if (full_recv(x->fd, HEAD_SIZE, x->buffer)) return H3C_ERECV; + + struct head head = {0}; + head_parse(&head, x->buffer); + + // We expect eslEFORMAT error for warmup: + // https://github.com/EddyRivasLab/easel/blob/07ca83ba9ef0414dba9ce0a9331d465b5eb58f2b/easel.h#L107 + if (head.status != 7) + { + discard(x->fd, head.msglen); + return H3C_EWARMUPCODE; + } + + return discard(x->fd, head.msglen) ? H3C_EDISCARD : 0; +} + +static int setup_buffer(struct h3c_socket *x, size_t required_size) +{ + if (required_size <= MIN_BUFFSIZE || required_size <= x->capacity) return 0; + + void *ptr = realloc(x->buffer, required_size); + if (!ptr) return H3C_ENOMEM; + x->capacity = required_size; + x->buffer = ptr; + return 0; +} + +int h3c_socket_send(struct h3c_socket *x, char const cmd[static 1], + char const seq[static 1]) +{ + sprintf((char *)x->buffer, "@%s\n>NAME\n%s\n//", cmd, seq); + + if (full_send(x->fd, strlen((char const *)x->buffer), x->buffer)) + return H3C_ESEND; + if (full_recv(x->fd, HEAD_SIZE, x->buffer)) return H3C_ERECV; + + struct head head = {0}; + head_parse(&head, x->buffer); + + int rc = setup_buffer(x, head.msglen); + if (rc) + { + discard(x->fd, head.msglen); + return rc; + } + + if (full_recv(x->fd, head.msglen, x->buffer)) return H3C_ERECV; + + if (head.status) return 0; + + return body_parse(x->body, head.msglen, x->buffer); +} + +int h3c_socket_recv(struct h3c_socket *x, struct h3r *r) +{ + return body_store(x->body, r); +} + +int h3c_socket_hangup(struct h3c_socket *x) +{ + if (shutdown(x->fd, SHUT_RDWR) < 0) + { + perror("Shutdown failed"); + close(x->fd); + return 1; + } + + return 0; +} + +void h3c_socket_del(struct h3c_socket const *x) +{ + if (x) + { + if (close(x->fd)) perror("Socket close failed"); + free(x->buffer); + body_del(x->body); + } + free((void *)x); +} diff --git a/h3client/h3c_socket.h b/h3client/h3c_socket.h new file mode 100644 index 0000000..90df227 --- /dev/null +++ b/h3client/h3c_socket.h @@ -0,0 +1,15 @@ +#ifndef H3C_SOCKET_H +#define H3C_SOCKET_H + +struct h3c_socket; +struct h3r; + +struct h3c_socket *h3c_socket_new(void); +int h3c_socket_dial(struct h3c_socket *, char const *ip, int port, long timeout); +int h3c_socket_warmup(struct h3c_socket *); +int h3c_socket_send(struct h3c_socket *, char const cmd[static 1], char const seq[static 1]); +int h3c_socket_recv(struct h3c_socket *, struct h3r *); +int h3c_socket_hangup(struct h3c_socket *); +void h3c_socket_del(struct h3c_socket const *); + +#endif diff --git a/h3client/h3c_stream.c b/h3client/h3c_stream.c deleted file mode 100644 index 07130d9..0000000 --- a/h3client/h3c_stream.c +++ /dev/null @@ -1,81 +0,0 @@ -#include "h3c_stream.h" -#include "answer.h" -#include "cco.h" -#include "h3c_errno.h" -#include "h3c_result.h" -#include "msg.h" -#include "nng/nng.h" -#include - -struct h3client_stream -{ - struct nng_stream *stream; - struct cco_queue queue; -}; - -struct h3client_stream *h3client_stream_new(struct nng_stream *stream) -{ - if (!stream) return NULL; - - struct h3client_stream *task = malloc(sizeof(*task)); - if (!task) return NULL; - - task->stream = stream; - cco_queue_init(&task->queue); - return task; -} - -int h3client_stream_put(struct h3client_stream *t, char const *args, - char const *name, char const *seq, long deadline) -{ - struct msg *msg = h3client_msg_new(t->stream); - if (!msg) return H3C_ENOMEM; - - h3client_stream_wait(t); - int rc = h3client_msg_start(msg, args, name, seq, deadline); - if (rc) - { - h3client_msg_del(msg); - return rc; - } - - cco_queue_put(&t->queue, &msg->node); - - return 0; -} - -void h3client_stream_wait(struct h3client_stream *t) -{ - if (cco_queue_empty(&t->queue)) return; - struct msg *msg = cco_of(cco_queue_pop(&t->queue), struct msg, node); - h3client_msg_wait(msg); - cco_queue_put_first(&t->queue, &msg->node); -} - -int h3client_stream_pop(struct h3client_stream *t, struct h3c_result *r) -{ - struct msg *msg = cco_of(cco_queue_pop(&t->queue), struct msg, node); - int rc = h3client_msg_result(msg); - if (rc) - { - h3client_msg_del(msg); - return rc; - } - rc = h3client_answer_copy(h3client_msg_answer(msg), r); - h3client_msg_del(msg); - return rc; -} - -void h3client_stream_del(struct h3client_stream *t) -{ - if (!t) return; - while (!cco_queue_empty(&t->queue)) - { - h3client_stream_wait(t); - struct msg *msg = cco_of(cco_queue_pop(&t->queue), struct msg, node); - h3client_msg_del(msg); - } - nng_stream_close(t->stream); - nng_stream_free(t->stream); - free(t); -} diff --git a/h3client/h3c_stream.h b/h3client/h3c_stream.h deleted file mode 100644 index fb8f7ab..0000000 --- a/h3client/h3c_stream.h +++ /dev/null @@ -1,14 +0,0 @@ -#ifndef H3C_STREAM_H -#define H3C_STREAM_H - -struct nng_stream; -struct h3client_stream; -struct h3c_result; - -struct h3client_stream * h3client_stream_new(struct nng_stream *); -int h3client_stream_put(struct h3client_stream *, char const *args, char const *name, char const *seq, long deadline); -void h3client_stream_wait(struct h3client_stream *); -int h3client_stream_pop(struct h3client_stream *, struct h3c_result *); -void h3client_stream_del(struct h3client_stream *); - -#endif diff --git a/h3client/h3c_strerror.h b/h3client/h3c_strerror.h deleted file mode 100644 index ac70fd3..0000000 --- a/h3client/h3c_strerror.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef H3C_STRERROR_H -#define H3C_STRERROR_H - -char const *h3client_strerror(int err); - -#endif diff --git a/h3client/head.h b/h3client/head.h new file mode 100644 index 0000000..f195a81 --- /dev/null +++ b/h3client/head.h @@ -0,0 +1,22 @@ +#ifndef HEAD_H +#define HEAD_H + +#include "parse.h" +#include +#include + +struct head +{ + uint32_t status; + uint64_t msglen; +}; + +#define HEAD_SIZE (sizeof(uint32_t) + sizeof(uint64_t)) + +static void head_parse(struct head *x, unsigned char const buffer[HEAD_SIZE]) +{ + x->status = parse_uint32(buffer); + x->msglen = parse_uint64(buffer + 4); +} + +#endif diff --git a/h3client/helper.c b/h3client/helper.c deleted file mode 100644 index bca33d1..0000000 --- a/h3client/helper.c +++ /dev/null @@ -1,23 +0,0 @@ -#include "helper.h" - -struct query const ross[2] = { - [GOOD] = {.name = "tr|Q949S7|Q949S7_ARATH", - .desc = "NAD(P)-binding Rossmann-fold superfamily protein " - "OS=Arabidopsis thaliana OX=3702 GN=At5g15910 PE=1 SV=1", - .seq = - "MLRSLIWKRSQAYSSVVTMSSISQRGNERLLSEVAGSHSRDNKILVLGGNGYVGSHICKE" - "ALRQGFSVSSLSRSGRSSLHDSWVDDVTWHQGDLLSPDSLKPALEGITSVISCVGGFGSN" - "SQMVRINGTANINAVKAAAEQGVKRFVYISAADFGVINNLIRGYFEGKRATEAEILDKFG" - "NRGSVLRPGFIHGTRQVGSIKLPLSLIGAPLEMVLKLLPKEVTKIPVIGPLLIPPVNVKS" - "VAATAVKAAVDPEFASGVIDVYRILQHGH", - .expect = {.nhits = 4, .ln_evalue = -53.808984215028}}, - [BAD] = {.name = ">tr|Q|Q_ARATH", - .desc = "NAD(P)-binding Rossmann-fold", - .seq = "MLRSLIWRSQAYSSVVTMSSISQRGNERLLSEVAGSHSRDNKILVLGNGYVGSHICKE" - "SQMVRINGTANINAVKAAAEQGVKRFVYISADFGVINNLIRGYFEGKRATEAEILDKF" - "NRGSVLRPGFIHGTRQVGSIKLPLSLIGAPLMVLKLLPKEVTKIPVIGPLLIPPVNVS" - "TAATAVKAAVDPEFASGVIDVYRILQHGH", - .expect = {.nhits = 0, .ln_evalue = 0}}}; - -struct query const corrupt[1] = { - [0] = {.name = ">a", .desc = "", .seq = "__FF", .expect = {.nhits = 0}}}; diff --git a/h3client/helper.h b/h3client/helper.h deleted file mode 100644 index f255110..0000000 --- a/h3client/helper.h +++ /dev/null @@ -1,26 +0,0 @@ -#ifndef HELPER_H -#define HELPER_H - -#define array_size(arr) (sizeof(arr) / sizeof((arr)[0])) - -#define GOOD 0 -#define BAD 1 - -struct expect -{ - unsigned nhits; - double ln_evalue; -}; - -struct query -{ - char const *name; - char const *desc; - char const *seq; - struct expect expect; -}; - -extern struct query const ross[2]; -extern struct query const corrupt[1]; - -#endif diff --git a/h3client/hmmd_alidisplay.c b/h3client/hmmd_alidisplay.c deleted file mode 100644 index 8590ddc..0000000 --- a/h3client/hmmd_alidisplay.c +++ /dev/null @@ -1,104 +0,0 @@ -#include "hmmd_alidisplay.h" -#include "compiler.h" -#include "defer_return.h" -#include "h3c_errno.h" -#include "utils.h" -#include "zc.h" -#include -#include - -void h3client_hmmd_alidisplay_init(struct hmmd_alidisplay *ali) -{ - memset(ali, 0, sizeof(*ali)); -} - -void h3client_hmmd_alidisplay_cleanup(struct hmmd_alidisplay *ali) -{ - free(ali->mem); - ali->mem = NULL; - h3client_hmmd_alidisplay_init(ali); -} - -static_assert(sizeof(int) == sizeof(uint32_t), "HMMER3 undefired requirement"); -#define SER_BASE_SIZE ((5 * sizeof(int)) + (3 * sizeof(int64_t)) + 1) - -#define RFLINE_PRESENT (1 << 0) -#define MMLINE_PRESENT (1 << 1) -#define CSLINE_PRESENT (1 << 2) -#define PPLINE_PRESENT (1 << 3) -#define ASEQ_PRESENT (1 << 4) -#define NTSEQ_PRESENT (1 << 5) - -static bool parse_strings(struct hmmd_alidisplay *ali, size_t size, char **mem) -{ - unsigned nstrings = 0; - nstrings += !!(ali->presence & RFLINE_PRESENT); - nstrings += !!(ali->presence & MMLINE_PRESENT); - nstrings += !!(ali->presence & CSLINE_PRESENT); - nstrings += 2; - nstrings += !!(ali->presence & ASEQ_PRESENT); - nstrings += !!(ali->presence & NTSEQ_PRESENT); - nstrings += !!(ali->presence & PPLINE_PRESENT); - nstrings += 6; - - if (!h3client_expect_n_strings(size, *mem, nstrings)) return false; - - ali->rfline = ali->presence & RFLINE_PRESENT ? h3client_strskip(mem) : 0; - ali->mmline = ali->presence & MMLINE_PRESENT ? h3client_strskip(mem) : 0; - ali->csline = ali->presence & CSLINE_PRESENT ? h3client_strskip(mem) : 0; - ali->model = h3client_strskip(mem); - ali->mline = h3client_strskip(mem); - ali->aseq = ali->presence & ASEQ_PRESENT ? h3client_strskip(mem) : 0; - ali->ntseq = ali->presence & NTSEQ_PRESENT ? h3client_strskip(mem) : 0; - ali->ppline = ali->presence & PPLINE_PRESENT ? h3client_strskip(mem) : 0; - - ali->hmmname = h3client_strskip(mem); - ali->hmmacc = h3client_strskip(mem); - ali->hmmdesc = h3client_strskip(mem); - ali->sqname = h3client_strskip(mem); - ali->sqacc = h3client_strskip(mem); - ali->sqdesc = h3client_strskip(mem); - - return true; -} - -int h3client_hmmd_alidisplay_parse(struct hmmd_alidisplay *ali, - unsigned char const **ptr, - unsigned char const *end) -{ - int rc = 0; - - if (end < *ptr + sizeof(uint32_t)) defer_return(H3C_EPARSE); - - size_t obj_size = h3client_eatu32(ptr); - if (obj_size <= SER_BASE_SIZE) defer_return(H3C_EPARSE); - size_t memsize = (size_t)(obj_size - SER_BASE_SIZE); - - if (!(ali->mem = zc_reallocf(ali->mem, memsize))) defer_return(H3C_ENOMEM); - ali->memsize = memsize; - - if (end < *ptr + 4 * sizeof(uint32_t) + 3 * sizeof(uint64_t)) defer_return(H3C_EPARSE); - ali->N = h3client_eatu32(ptr); - ali->hmmfrom = h3client_eatu32(ptr); - ali->hmmto = h3client_eatu32(ptr); - ali->M = h3client_eatu32(ptr); - ali->sqfrom = h3client_eatu64(ptr); - ali->sqto = h3client_eatu64(ptr); - ali->L = h3client_eatu64(ptr); - - if (end < *ptr + sizeof(uint8_t)) defer_return(H3C_EPARSE); - ali->presence = h3client_eatu8(ptr); - - if (end < *ptr + memsize) defer_return(H3C_EPARSE); - memcpy(ali->mem, *ptr, memsize); - *ptr += memsize; - - char *mem = ali->mem; - if (!parse_strings(ali, ali->memsize, &mem)) defer_return(H3C_EPARSE); - - return 0; - -defer: - h3client_hmmd_alidisplay_cleanup(ali); - return rc; -} diff --git a/h3client/hmmd_alidisplay.h b/h3client/hmmd_alidisplay.h deleted file mode 100644 index 6c42326..0000000 --- a/h3client/hmmd_alidisplay.h +++ /dev/null @@ -1,46 +0,0 @@ -#ifndef HMMD_ALIDISPLAY_H -#define HMMD_ALIDISPLAY_H - -#include -#include -#include - -struct hmmd_alidisplay -{ - uint8_t presence; - - char *rfline; - char *mmline; - char *csline; - char *model; - char *mline; - char *aseq; - char *ntseq; - char *ppline; - uint32_t N; - - char *hmmname; - char *hmmacc; - char *hmmdesc; - uint32_t hmmfrom; - uint32_t hmmto; - uint32_t M; - - char *sqname; - char *sqacc; - char *sqdesc; - uint64_t sqfrom; - uint64_t sqto; - uint64_t L; - - size_t memsize; - char *mem; -}; - -void h3client_hmmd_alidisplay_init(struct hmmd_alidisplay *); -void h3client_hmmd_alidisplay_cleanup(struct hmmd_alidisplay *); -int h3client_hmmd_alidisplay_parse(struct hmmd_alidisplay *, - unsigned char const **ptr, - unsigned char const *end); - -#endif diff --git a/h3client/hmmd_domain.c b/h3client/hmmd_domain.c deleted file mode 100644 index 0b45450..0000000 --- a/h3client/hmmd_domain.c +++ /dev/null @@ -1,80 +0,0 @@ -#include "hmmd_domain.h" -#include "compiler.h" -#include "defer_return.h" -#include "h3c_errno.h" -#include "hmmd_alidisplay.h" -#include "utils.h" -#include -#include - -void h3client_hmmd_domain_init(struct hmmd_domain *dom) -{ - memset(dom, 0, offsetof(struct hmmd_domain, ad)); - h3client_hmmd_alidisplay_init(&dom->ad); -} - -void h3client_hmmd_domain_cleanup(struct hmmd_domain *dom) -{ - if (dom->pos_score) free(dom->pos_score); - h3client_hmmd_alidisplay_cleanup(&dom->ad); - h3client_hmmd_domain_init(dom); -} - -static_assert(sizeof(float) == 4, "sizeof(float) == 4"); -static_assert(sizeof(double) == 8, "sizeof(double) == 8"); - -int h3client_hmmd_domain_parse(struct hmmd_domain *dom, - unsigned char const **ptr, - unsigned char const *end) -{ - int rc = 0; - - if (end < *ptr + sizeof(uint32_t) + 6 * sizeof(uint64_t)) defer_return(H3C_EPARSE); - - // Skips object size - (void)h3client_eatu32(ptr); - dom->ienv = h3client_eatu64(ptr); - dom->jenv = h3client_eatu64(ptr); - dom->iali = h3client_eatu64(ptr); - dom->jali = h3client_eatu64(ptr); - - // Skips iorf and jorf. - (void)h3client_eati64(ptr); - (void)h3client_eati64(ptr); - - if (end < *ptr + 5 * sizeof(float) + sizeof(double)) defer_return(H3C_EPARSE); - if (end < *ptr + 3 * sizeof(uint32_t)) defer_return(H3C_EPARSE); - - dom->envsc = h3client_eatf32(ptr); - dom->domcorrection = h3client_eatf32(ptr); - dom->dombias = h3client_eatf32(ptr); - dom->oasc = h3client_eatf32(ptr); - dom->bitscore = h3client_eatf32(ptr); - dom->lnP = h3client_eatf64(ptr); - dom->is_reported = h3client_eatu32(ptr); - dom->is_included = h3client_eatu32(ptr); - - uint32_t scores_size = h3client_eatu32(ptr); - - if (scores_size > dom->scores_size) - { - size_t size = scores_size * sizeof(float); - float *scores = realloc(dom->pos_score, size); - if (!scores) defer_return(H3C_EPARSE); - dom->pos_score = scores; - dom->scores_size = scores_size; - } - else - dom->scores_size = scores_size; - - if (end < *ptr + dom->scores_size * sizeof(float)) defer_return(H3C_EPARSE); - for (uint32_t i = 0; i < dom->scores_size; i++) - dom->pos_score[i] = h3client_eatf32(ptr); - - if ((rc = h3client_hmmd_alidisplay_parse(&dom->ad, ptr, end))) defer_return(rc); - - return 0; - -defer: - return rc; -} diff --git a/h3client/hmmd_domain.h b/h3client/hmmd_domain.h deleted file mode 100644 index 47ec6f2..0000000 --- a/h3client/hmmd_domain.h +++ /dev/null @@ -1,36 +0,0 @@ -#ifndef HMMD_DOMAIN_H -#define HMMD_DOMAIN_H - -#include "hmmd_alidisplay.h" -#include -#include -#include - -struct hmmd_domain -{ - uint32_t ienv; - uint32_t jenv; - uint32_t iali; - uint32_t jali; - // The following two members seems to be receiving - // random numbers from daemon end. Skip them. - // int64_t iorf, jorf; - float envsc; - float domcorrection; - float dombias; - float oasc; - float bitscore; - double lnP; - bool is_reported; - bool is_included; - uint32_t scores_size; - float *pos_score; - struct hmmd_alidisplay ad; -}; - -void h3client_hmmd_domain_init(struct hmmd_domain *); -void h3client_hmmd_domain_cleanup(struct hmmd_domain *); -int h3client_hmmd_domain_parse(struct hmmd_domain *, unsigned char const **ptr, - unsigned char const *end); - -#endif diff --git a/h3client/hmmd_hit.c b/h3client/hmmd_hit.c deleted file mode 100644 index 5e15e7e..0000000 --- a/h3client/hmmd_hit.c +++ /dev/null @@ -1,131 +0,0 @@ -#include "hmmd_hit.h" -#include "defer_return.h" -#include "h3c_errno.h" -#include "hmmd_domain.h" -#include "utils.h" -#include -#include - -void h3client_hmmd_hit_init(struct hmmd_hit *hit) -{ - memset(hit, 0, sizeof(*hit)); -} - -void h3client_hmmd_hit_cleanup(struct hmmd_hit *hit) -{ - if (hit->name) free(hit->name); - if (hit->acc) free(hit->acc); - if (hit->desc) free(hit->desc); - - for (unsigned i = 0; i < hit->ndom; i++) - h3client_hmmd_domain_cleanup(hit->dcl + i); - - free(hit->dcl); - h3client_hmmd_hit_init(hit); -} - -#define ACC_PRESENT (1 << 0) -#define DESC_PRESENT (1 << 1) - -static int parse_strings(struct hmmd_hit *hit, uint8_t presence, size_t size, - unsigned char const **ptr) -{ - unsigned n = 1 + !!(presence & ACC_PRESENT) + !!(presence & DESC_PRESENT); - if (!h3client_expect_n_strings(size, (char const *)*ptr, n)) - return H3C_EPARSE; - - int rc = 0; - - if ((rc = h3client_eatstr(&hit->name, ptr))) return rc; - - if (presence & ACC_PRESENT) - { - if ((rc = h3client_eatstr(&hit->acc, ptr))) return rc; - } - - if (presence & DESC_PRESENT) - { - if ((rc = h3client_eatstr(&hit->desc, ptr))) return rc; - } - - return 0; -} - -int h3client_hmmd_hit_parse(struct hmmd_hit *hit, unsigned char const **ptr, - unsigned char const *end) -{ - int rc = 0; - - if (end < *ptr + 2 * sizeof(uint32_t)) defer_return(H3C_EPARSE); - - // Skips object size - (void)h3client_eatu32(ptr); - - // Skips window_length for now - (void)h3client_eati32(ptr); - - if (end < *ptr + 4 * sizeof(double) + 3 * sizeof(float)) - defer_return(H3C_EPARSE); - hit->sortkey = h3client_eatf64(ptr); - hit->score = h3client_eatf32(ptr); - hit->pre_score = h3client_eatf32(ptr); - hit->sum_score = h3client_eatf32(ptr); - - hit->lnP = h3client_eatf64(ptr); - hit->pre_lnP = h3client_eatf64(ptr); - hit->sum_lnP = h3client_eatf64(ptr); - - if (end < *ptr + 5 * sizeof(uint32_t) + sizeof(float)) - defer_return(H3C_EPARSE); - hit->nexpected = h3client_eatf32(ptr); - hit->nregions = h3client_eatu32(ptr); - hit->nclustered = h3client_eatu32(ptr); - hit->noverlaps = h3client_eatu32(ptr); - hit->nenvelopes = h3client_eatu32(ptr); - uint32_t ndom = h3client_eatu32(ptr); - - if (end < *ptr + 4 * sizeof(uint32_t) + 2 * sizeof(uint64_t)) - defer_return(H3C_EPARSE); - hit->flags = h3client_eatu32(ptr); - hit->nreported = h3client_eatu32(ptr); - hit->nincluded = h3client_eatu32(ptr); - hit->best_domain = h3client_eatu32(ptr); - // Skips seqidx - (void)h3client_eatu64(ptr); - // Skips subseq_start for now - (void)h3client_eatu64(ptr); - - if (end < *ptr + sizeof(uint8_t)) defer_return(H3C_EPARSE); - uint8_t presence = h3client_eatu8(ptr); - - if ((rc = parse_strings(hit, presence, (end - *ptr), ptr))) defer_return(rc); - - if (ndom > hit->ndom) - { - struct hmmd_domain *dcl = realloc(hit->dcl, ndom * sizeof(*hit->dcl)); - if (!dcl) defer_return(H3C_ENOMEM); - - hit->dcl = dcl; - for (uint32_t i = hit->ndom; i < ndom; i++) - { - h3client_hmmd_domain_init(hit->dcl + i); - ++hit->ndom; - } - } - else - { - for (uint32_t i = ndom; i < hit->ndom; i++) - h3client_hmmd_domain_cleanup(hit->dcl + i); - hit->ndom = ndom; - } - - for (uint32_t i = 0; i < hit->ndom; i++) - { - if ((rc = h3client_hmmd_domain_parse(hit->dcl + i, ptr, end))) defer_return(rc); - } - - return 0; - -defer: - return rc; -} diff --git a/h3client/hmmd_hit.h b/h3client/hmmd_hit.h deleted file mode 100644 index 764c201..0000000 --- a/h3client/hmmd_hit.h +++ /dev/null @@ -1,54 +0,0 @@ -#ifndef HMMD_HIT_H -#define HMMD_HIT_H - -#include -#include - -struct hmmd_domain; - -struct hmmd_hit -{ - char *name; - char *acc; - char *desc; - // The following members seem to be receiving - // random numbers from daemon end. Skip them. - // int window_length; - double sortkey; - - float score; - float pre_score; - float sum_score; - - double lnP; - double pre_lnP; - double sum_lnP; - - float nexpected; - uint32_t nregions; - uint32_t nclustered; - uint32_t noverlaps; - uint32_t nenvelopes; - uint32_t ndom; - - uint32_t flags; - uint32_t nreported; - uint32_t nincluded; - uint32_t best_domain; - - // Skip it. - // uint64_t seqidx; - // The following member seems to be receiving - // random numbers from daemon end. Skip it. - // uint64_t subseq_start; - - struct hmmd_domain *dcl; -}; - -void h3client_hmmd_hit_init(struct hmmd_hit *); -void h3client_hmmd_hit_cleanup(struct hmmd_hit *); - -int h3client_hmmd_hit_parse(struct hmmd_hit *hit, unsigned char const **ptr, - unsigned char const *end); - -#endif diff --git a/h3client/hmmd_hmmd.h b/h3client/hmmd_hmmd.h deleted file mode 100644 index fbec267..0000000 --- a/h3client/hmmd_hmmd.h +++ /dev/null @@ -1,13 +0,0 @@ -#ifndef HMMD_HMMD_H -#define HMMD_HMMD_H - -#include "hmmd_domain.h" -#include "hmmd_hit.h" -#include "hmmd_stats.h" -#include "hmmd_status.h" -#include "hmmd_tophits.h" -#include - -#define HMMD_STATUS_PACK_SIZE (sizeof(uint32_t) + sizeof(uint64_t)) - -#endif diff --git a/h3client/hmmd_stats.c b/h3client/hmmd_stats.c deleted file mode 100644 index c934ec8..0000000 --- a/h3client/hmmd_stats.c +++ /dev/null @@ -1,84 +0,0 @@ -#include "hmmd_stats.h" -#include "defer_return.h" -#include "h3c_errno.h" -#include "hmmd_zsetby.h" -#include "utils.h" -#include "zc.h" -#include -#include -#include - -void h3client_hmmd_stats_init(struct hmmd_stats *stats) -{ - memset(stats, 0, sizeof(*stats)); -} - -void h3client_hmmd_stats_cleanup(struct hmmd_stats *stats) -{ - free(stats->hit_offsets); - stats->hit_offsets = 0; -} - -static int parse_first_part(struct hmmd_stats *stats, unsigned char const **ptr, - unsigned char const *end) -{ - int rc = 0; - - if (end < *ptr + 14 * sizeof(uint64_t) + 2) defer_return(H3C_EPARSE); - - // skip elapsed - (void)h3client_eatf64(ptr); - // skip user - (void)h3client_eatf64(ptr); - // skip sys - (void)h3client_eatf64(ptr); - - stats->Z = h3client_eatf64(ptr); - stats->domZ = h3client_eatf64(ptr); - - if ((rc = h3client_hmmd_zsetby_parse(&stats->Z_setby, ptr))) defer_return(rc); - if ((rc = h3client_hmmd_zsetby_parse(&stats->domZ_setby, ptr))) defer_return(rc); - - stats->nmodels = h3client_eatu64(ptr); - stats->nseqs = h3client_eatu64(ptr); - stats->n_past_msv = h3client_eatu64(ptr); - stats->n_past_bias = h3client_eatu64(ptr); - stats->n_past_vit = h3client_eatu64(ptr); - stats->n_past_fwd = h3client_eatu64(ptr); - stats->nhits = h3client_eatu64(ptr); - stats->nreported = h3client_eatu64(ptr); - stats->nincluded = h3client_eatu64(ptr); - -defer: - return rc; -} - -int h3client_hmmd_stats_parse(struct hmmd_stats *stats, - unsigned char const **ptr, - unsigned char const *end) -{ - int rc = 0; - - if ((rc = parse_first_part(stats, ptr, end))) defer_return(rc); - - if (end < *ptr + sizeof(uint64_t)) defer_return(H3C_EPARSE); - uint64_t hit_offset = h3client_eatu64(ptr); - - if (hit_offset == UINT64_MAX && stats->nhits > 0) defer_return(H3C_EPARSE); - - size_t size = stats->nhits * sizeof(uint64_t); - if (hit_offset == UINT64_MAX || size == 0) return 0; - - stats->hit_offsets = zc_reallocf(stats->hit_offsets, size); - if (!stats->hit_offsets) defer_return(H3C_ENOMEM); - - if (end < *ptr + stats->nhits * sizeof(uint64_t)) defer_return(H3C_EPARSE); - stats->hit_offsets[0] = hit_offset; - for (uint64_t i = 1; i < stats->nhits; i++) - stats->hit_offsets[i] = h3client_eatu64(ptr); - - return 0; - -defer: - return rc; -} diff --git a/h3client/hmmd_stats.h b/h3client/hmmd_stats.h deleted file mode 100644 index 2498d21..0000000 --- a/h3client/hmmd_stats.h +++ /dev/null @@ -1,34 +0,0 @@ -#ifndef HMMD_STATS_H -#define HMMD_STATS_H - -#include "hmmd_zsetby.h" -#include -#include - -struct hmmd_stats -{ - double Z; - double domZ; - enum hmmd_zsetby Z_setby; - enum hmmd_zsetby domZ_setby; - - uint64_t nmodels; - uint64_t nseqs; - uint64_t n_past_msv; - uint64_t n_past_bias; - uint64_t n_past_vit; - uint64_t n_past_fwd; - - uint64_t nhits; - uint64_t nreported; - uint64_t nincluded; - uint64_t *hit_offsets; -}; - -void h3client_hmmd_stats_init(struct hmmd_stats *); -void h3client_hmmd_stats_cleanup(struct hmmd_stats *); -int h3client_hmmd_stats_parse(struct hmmd_stats *stats, - unsigned char const **ptr, - unsigned char const *end); - -#endif diff --git a/h3client/hmmd_status.c b/h3client/hmmd_status.c deleted file mode 100644 index 3e445be..0000000 --- a/h3client/hmmd_status.c +++ /dev/null @@ -1,19 +0,0 @@ -#include "hmmd_status.h" -#include "h3c_errno.h" -#include "utils.h" -#include -#include - -void h3client_hmmd_status_init(struct hmmd_status *st) -{ - memset(st, 0, sizeof(*st)); -} - -void h3client_hmmd_status_parse(struct hmmd_status *status, size_t *read_size, - unsigned char const *data) -{ - unsigned char const *ptr = data; - status->status = h3client_eatu32(&ptr); - status->msglen = h3client_eatu64(&ptr); - *read_size = (size_t)(ptr - data); -} diff --git a/h3client/hmmd_status.h b/h3client/hmmd_status.h deleted file mode 100644 index 592297a..0000000 --- a/h3client/hmmd_status.h +++ /dev/null @@ -1,18 +0,0 @@ -#ifndef HMMD_STATUS_H -#define HMMD_STATUS_H - -#include -#include - -struct hmmd_status -{ - uint32_t status; - uint64_t msglen; -}; - -void h3client_hmmd_status_init(struct hmmd_status *); - -void h3client_hmmd_status_parse(struct hmmd_status *status, size_t *read_size, - unsigned char const *data); - -#endif diff --git a/h3client/hmmd_tophits.c b/h3client/hmmd_tophits.c deleted file mode 100644 index cb9fe31..0000000 --- a/h3client/hmmd_tophits.c +++ /dev/null @@ -1,101 +0,0 @@ -#include "hmmd_tophits.h" -#include "h3c_errno.h" -#include "hmmd_hit.h" -#include "zc.h" -#include -#include -#include - -void h3client_hmmd_tophits_init(struct hmmd_tophits *th) -{ - memset(th, 0, sizeof(*th)); - th->hit = 0; - th->unsrt = 0; - th->is_sorted_by_sortkey = true; -} - -static int grow(struct hmmd_tophits *th, uint64_t nhits) -{ - int rc = 0; - - if (!(th->hit = zc_reallocf(th->hit, sizeof(*th->hit) * nhits))) - { - rc = H3C_ENOMEM; - goto cleanup; - } - - size_t sz = nhits * sizeof(*th->unsrt); - struct hmmd_hit *hits = realloc(th->unsrt, sz); - if (!hits) - { - rc = H3C_ENOMEM; - goto cleanup; - } - th->unsrt = hits; - - for (uint64_t i = th->nhits; i < nhits; ++i) - { - h3client_hmmd_hit_init(th->unsrt + i); - ++th->nhits; - } - - return 0; - -cleanup: - h3client_hmmd_tophits_cleanup(th); - return rc; -} - -static void shrink(struct hmmd_tophits *th, uint64_t nhits) -{ - for (uint64_t i = nhits; i < th->nhits; ++i) - { - th->hit[i] = 0; - h3client_hmmd_hit_cleanup(th->unsrt + i); - } - - th->nhits = nhits; -} - -int h3client_hmmd_tophits_setup(struct hmmd_tophits *th, - unsigned char const **ptr, - unsigned char const *end, uint64_t nhits, - uint64_t nreported, uint64_t nincluded) -{ - int rc = 0; - - if (th->nhits < nhits) - rc = grow(th, nhits); - else - shrink(th, nhits); - - if (rc) goto cleanup; - - th->nreported = nreported; - th->nincluded = nincluded; - th->is_sorted_by_seqidx = false; - th->is_sorted_by_sortkey = true; - - for (uint64_t i = 0; i < nhits; ++i) - { - if ((rc = h3client_hmmd_hit_parse(th->unsrt + i, ptr, end))) goto cleanup; - th->hit[i] = th->unsrt + i; - } - - return 0; - -cleanup: - h3client_hmmd_tophits_cleanup(th); - return rc; -} - -void h3client_hmmd_tophits_cleanup(struct hmmd_tophits *th) -{ - for (uint64_t i = 0; i < th->nhits; ++i) - { - h3client_hmmd_hit_cleanup(th->unsrt + i); - } - free(th->hit); - free(th->unsrt); - h3client_hmmd_tophits_init(th); -} diff --git a/h3client/hmmd_tophits.h b/h3client/hmmd_tophits.h deleted file mode 100644 index b37b7c0..0000000 --- a/h3client/hmmd_tophits.h +++ /dev/null @@ -1,27 +0,0 @@ -#ifndef HMMD_TOPHITS_H -#define HMMD_TOPHITS_H - -#include -#include - -struct hmmd_hit; - -struct hmmd_tophits -{ - struct hmmd_hit **hit; - struct hmmd_hit *unsrt; - uint64_t nhits; - uint64_t nreported; - uint64_t nincluded; - bool is_sorted_by_sortkey; - bool is_sorted_by_seqidx; -}; - -void h3client_hmmd_tophits_init(struct hmmd_tophits *); -int h3client_hmmd_tophits_setup(struct hmmd_tophits *, - unsigned char const **ptr, - unsigned char const *end, uint64_t nhits, - uint64_t nreported, uint64_t nincluded); -void h3client_hmmd_tophits_cleanup(struct hmmd_tophits *); - -#endif diff --git a/h3client/hmmd_zsetby.c b/h3client/hmmd_zsetby.c deleted file mode 100644 index 2733d40..0000000 --- a/h3client/hmmd_zsetby.c +++ /dev/null @@ -1,25 +0,0 @@ -#include "hmmd_zsetby.h" -#include "h3c_errno.h" - -int h3client_hmmd_zsetby_parse(enum hmmd_zsetby *dst, - unsigned char const **data) -{ - int rc = 0; - switch (**data) - { - case 0: - *dst = HMMD_ZSETBY_NTARGETS; - break; - case 1: - *dst = HMMD_ZSETBY_OPTION; - break; - case 2: - *dst = HMMD_ZSETBY_FILEINFO; - break; - default: - rc = H3C_EUNPACK; - break; - } - (*data) += 1; - return rc; -} diff --git a/h3client/hmmd_zsetby.h b/h3client/hmmd_zsetby.h deleted file mode 100644 index a066a2d..0000000 --- a/h3client/hmmd_zsetby.h +++ /dev/null @@ -1,16 +0,0 @@ -#ifndef HMMD_ZSETBY_H -#define HMMD_ZSETBY_H - -#include - -enum hmmd_zsetby -{ - HMMD_ZSETBY_NTARGETS = 0, - HMMD_ZSETBY_OPTION = 1, - HMMD_ZSETBY_FILEINFO = 2 -}; - -int h3client_hmmd_zsetby_parse(enum hmmd_zsetby *dst, - unsigned char const **data); - -#endif diff --git a/h3client/hmsg.c b/h3client/hmsg.c deleted file mode 100644 index e73f98f..0000000 --- a/h3client/hmsg.c +++ /dev/null @@ -1,151 +0,0 @@ -#include "hmsg.h" -#include "amsg.h" -#include "answer.h" -#include "h3c_errno.h" -#include "hmmd_hmmd.h" -#include "nng/nng.h" -#include "nnge.h" -#include "timeout.h" -#include -#include -#include - -enum state -{ - STATUS, - DATA, -}; - -struct hmsg -{ - enum state state; - struct nng_stream *stream; - struct nng_aio *aio; - struct answer *ans; - struct amsg *amsg0; - struct amsg *amsg1; - long deadline; -}; - -static void callback(void *arg) -{ - struct hmsg *x = arg; - int rc = nng_aio_result(x->aio); - if (rc != 0) - { - nng_aio_finish(x->aio, rc); - return; - } - - if (x->state == STATUS) - { - rc = h3client_aresult(x->amsg0); - if (rc != 0) - { - nng_aio_finish(x->aio, rc); - return; - } - struct hmmd_status const *status = h3client_answer_status_parse(x->ans); - size_t size = status->msglen; - - if ((rc = h3client_answer_setup_size(x->ans, size))) - { - nng_aio_finish(x->aio, NNG_ENOMEM); - return; - } - - void *data = h3client_answer_data(x->ans); - if (!(x->amsg1 = - h3client_arecv(x->stream, size, data, &callback, x, x->deadline))) - { - nng_aio_finish(x->aio, NNG_ENOMEM); - return; - } - h3client_astart(x->amsg1); - x->state = DATA; - } - else if (x->state == DATA) - { - rc = h3client_aresult(x->amsg1); - if (rc != 0) - { - nng_aio_finish(x->aio, rc); - return; - } - if (h3client_answer_status(x->ans)->status) - { - if ((rc = h3client_answer_parse_error(x->ans))) - { - nng_aio_finish(x->aio, NNG_EINVAL); - return; - } - } - else - { - if ((rc = h3client_answer_parse(x->ans))) - { - nng_aio_finish(x->aio, NNG_EINVAL); - return; - } - } - nng_aio_finish(x->aio, 0); - } -} - -struct hmsg *h3client_hrecv(struct nng_stream *stream, struct answer *ans, - void (*callb)(void *), void *arg, long deadline) -{ - struct hmsg *x = malloc(sizeof(*x)); - if (!x) return NULL; - - x->state = STATUS; - x->stream = NULL; - x->aio = NULL; - x->ans = NULL; - x->amsg0 = NULL; - x->amsg1 = NULL; - x->deadline = deadline; - - x->stream = stream; - if (nng_aio_alloc(&x->aio, callb, arg)) - { - h3client_hdel(x); - return NULL; - } - nng_aio_set_timeout(x->aio, h3client_timeout(deadline)); - nng_aio_begin(x->aio); - - x->ans = ans; - - void *data = h3client_answer_status_data(ans); - size_t size = h3client_answer_status_size(); - char *b = data; - for (int i = 0; i < (int)size; ++i) - b[i] = 0; - if (!(x->amsg0 = h3client_arecv(stream, size, data, &callback, x, deadline))) - { - h3client_hdel(x); - return NULL; - } - - return x; -} - -void h3client_hstart(struct hmsg *x) { h3client_astart(x->amsg0); } - -void h3client_hcancel(struct hmsg *x) { nng_aio_cancel(x->aio); } - -void h3client_hstop(struct hmsg *x) { nng_aio_stop(x->aio); } - -void h3client_hdel(struct hmsg *x) -{ - if (!x) return; - if (x->amsg1) h3client_adel(x->amsg1); - if (x->amsg0) h3client_adel(x->amsg0); - if (x->aio) nng_aio_free(x->aio); - free(x); -} - -int h3client_hresult(struct hmsg *x) { return nng_aio_result(x->aio); } - -struct answer *h3client_houtput(struct hmsg *x) { return x->ans; } diff --git a/h3client/hmsg.h b/h3client/hmsg.h deleted file mode 100644 index 4bcfb19..0000000 --- a/h3client/hmsg.h +++ /dev/null @@ -1,20 +0,0 @@ -#ifndef HMSG_H -#define HMSG_H - -#include - -struct answer; -struct hmsg; -struct nng_stream; - -struct hmsg *h3client_hrecv(struct nng_stream *, struct answer *, - void (*callb)(void *), void *arg, long deadline); -void h3client_hstart(struct hmsg *); -void h3client_hcancel(struct hmsg *); -void h3client_hstop(struct hmsg *); -void h3client_hdel(struct hmsg *); - -int h3client_hresult(struct hmsg *); -struct answer *h3client_houtput(struct hmsg *); - -#endif diff --git a/h3client/itoa.c b/h3client/itoa.c deleted file mode 100644 index b19efbb..0000000 --- a/h3client/itoa.c +++ /dev/null @@ -1,36 +0,0 @@ -#include "itoa.h" - -static void reverse(signed char buf[], int size) -{ - signed char *end = buf + size - 1; - - while (buf < end) - { - signed char tmp = *buf; - *buf = *end; - *end = tmp; - buf++; - end--; - } -} - -// ACK: nanoprintf -static int itoa_rev(char *buf, int i) -{ - int n = 0; - const int sign = (i >= 0) ? 1 : -1; - do - { - *buf++ = (char)('0' + (sign * (i % 10))); - i /= 10; - ++n; - } while (i); - return n; -} - -int h3client_itoa(char *buf, int i) -{ - int n = itoa_rev(buf, i); - reverse((signed char *)buf, n); - return n; -} diff --git a/h3client/itoa.h b/h3client/itoa.h deleted file mode 100644 index 830a3e3..0000000 --- a/h3client/itoa.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef ITOA_H -#define ITOA_H - -int h3client_itoa(char *buf, int i); - -#endif diff --git a/h3client/little_endian.h b/h3client/little_endian.h new file mode 100644 index 0000000..950b591 --- /dev/null +++ b/h3client/little_endian.h @@ -0,0 +1,16 @@ +#ifndef LITTLE_ENDIAN_H +#define LITTLE_ENDIAN_H + +#include + +static inline int little_endian(void) +{ + const union + { + uint32_t u; + uint8_t c[4]; + } one = {.u = 1}; + return one.c[0]; +} + +#endif diff --git a/h3client/msg.c b/h3client/msg.c deleted file mode 100644 index fa9dbfe..0000000 --- a/h3client/msg.c +++ /dev/null @@ -1,150 +0,0 @@ -#include "msg.h" -#include "amsg.h" -#include "answer.h" -#include "array_size.h" -#include "h3c_errno.h" -#include "hmsg.h" -#include "nng/nng.h" -#include "nng/supplemental/util/platform.h" -#include "nnge.h" -#include "timeout.h" -#include -#include - -struct msg *h3client_msg_new(struct nng_stream *stream) -{ - struct msg *x = malloc(sizeof(*x)); - if (!x) return x; - - x->stream = stream; - x->state = 0; - x->deadline = 0; - x->aio = NULL; - x->ans = NULL; - x->send_amsg = NULL; - x->recv_hmsg = NULL; - x->mtx = NULL; - cco_node_init(&x->node); - - if (nng_aio_alloc(&x->aio, NULL, NULL)) - { - free(x); - return NULL; - } - - if (!(x->ans = h3client_answer_new())) - { - nng_aio_free(x->aio); - free(x); - return NULL; - } - - if (nng_mtx_alloc(&x->mtx)) - { - h3client_answer_del(x->ans); - nng_aio_free(x->aio); - free(x); - return NULL; - } - - return x; -} - -static void callback(void *arg); - -int h3client_msg_start(struct msg *x, char const *args, char const *name, - char const *seq, long deadline) -{ - struct nng_iov iov[] = { - {.iov_buf = "@", .iov_len = 1}, - {.iov_buf = (void *)args, .iov_len = strlen(args)}, - {.iov_buf = "\n>", .iov_len = 2}, - {.iov_buf = (void *)name, .iov_len = strlen(name)}, - {.iov_buf = "\n", .iov_len = 1}, - {.iov_buf = (void *)seq, .iov_len = strlen(seq)}, - {.iov_buf = "\n//", .iov_len = 3}, - }; - x->state = SEND; - x->deadline = deadline; - - nng_aio_set_timeout(x->aio, h3client_timeout(deadline)); - nng_aio_begin(x->aio); - - if (!(x->send_amsg = h3client_asend(x->stream, array_size(iov), iov, - &callback, x, deadline))) - return H3C_ENOMEM; - - h3client_astart(x->send_amsg); - return 0; -} - -void h3client_msg_wait(struct msg *x) { nng_aio_wait(x->aio); } - -int h3client_msg_result(struct msg *x) -{ - return h3client_nnge(nng_aio_result(x->aio)); -} - -void h3client_msg_cancel(struct msg *x) -{ - nng_mtx_lock(x->mtx); - if (x->recv_hmsg) h3client_hcancel(x->recv_hmsg); - nng_mtx_unlock(x->mtx); - h3client_acancel(x->send_amsg); - nng_aio_cancel(x->aio); -} - -void h3client_msg_stop(struct msg *x) -{ - nng_mtx_lock(x->mtx); - if (x->recv_hmsg) h3client_hstop(x->recv_hmsg); - nng_mtx_unlock(x->mtx); - h3client_astop(x->send_amsg); - nng_aio_stop(x->aio); -} - -void h3client_msg_del(struct msg const *x) -{ - if (!x) return; - if (x->ans) h3client_answer_del(x->ans); - if (x->send_amsg) h3client_adel(x->send_amsg); - nng_mtx_lock(x->mtx); - if (x->recv_hmsg) h3client_hdel(x->recv_hmsg); - nng_mtx_unlock(x->mtx); - if (x->mtx) nng_mtx_free(x->mtx); - if (x->aio) nng_aio_free(x->aio); - free((void *)x); -} - -struct answer *h3client_msg_answer(struct msg *x) { return x->ans; } - -static void callback(void *arg) -{ - struct msg *x = arg; - - if (x->state == SEND) - { - int rc = h3client_aresult(x->send_amsg); - if (rc) - { - nng_aio_finish(x->aio, rc); - return; - } - - nng_mtx_lock(x->mtx); - x->recv_hmsg = h3client_hrecv(x->stream, x->ans, &callback, x, x->deadline); - nng_mtx_unlock(x->mtx); - if (!x->recv_hmsg) - { - nng_aio_finish(x->aio, H3C_ENOMEM); - return; - } - - x->state = RECV; - h3client_hstart(x->recv_hmsg); - } - else if (x->state == RECV) - { - nng_aio_finish(x->aio, h3client_hresult(x->recv_hmsg)); - } -} diff --git a/h3client/msg.h b/h3client/msg.h deleted file mode 100644 index 9bc4142..0000000 --- a/h3client/msg.h +++ /dev/null @@ -1,37 +0,0 @@ -#ifndef MSG_H -#define MSG_H - -#include "cco.h" - -enum state -{ - SEND, - RECV, -}; - -struct msg -{ - struct nng_stream *stream; - enum state state; - long deadline; - struct nng_aio *aio; - struct answer *ans; - struct amsg *send_amsg; - struct hmsg *recv_hmsg; - struct nng_mtx *mtx; - struct cco_node node; -}; - -struct h3client_result; - -struct msg *h3client_msg_new(struct nng_stream *); -int h3client_msg_start(struct msg *, char const *args, char const *name, - char const *seq, long deadline); -void h3client_msg_wait(struct msg *); -int h3client_msg_result(struct msg *); -void h3client_msg_cancel(struct msg *); -void h3client_msg_stop(struct msg *); -void h3client_msg_del(struct msg const *); -struct answer *h3client_msg_answer(struct msg *); - -#endif diff --git a/h3client/nnge.c b/h3client/nnge.c deleted file mode 100644 index 43d7f55..0000000 --- a/h3client/nnge.c +++ /dev/null @@ -1,20 +0,0 @@ -#include "nnge.h" -#include "h3c_errno.h" -#include "nng/nng.h" - -int h3client_nnge(int c) -{ - if (c == NNG_ETIMEDOUT) return H3C_ETIMEDOUT; - if (c == NNG_ECANCELED) return H3C_ECANCELED; - if (c == NNG_EADDRINVAL) return H3C_EADDRINVAL; - if (c == NNG_ECLOSED) return H3C_ECLOSED; - if (c == NNG_ECONNREFUSED) return H3C_ECONNREFUSED; - if (c == NNG_ECONNRESET) return H3C_ECONNRESET; - if (c == NNG_EINVAL) return H3C_EINVAL; - if (c == NNG_ENOMEM) return H3C_ENOMEM; - if (c == NNG_EPEERAUTH) return H3C_EPEERAUTH; - if (c == NNG_EPROTO) return H3C_EPROTO; - if (c == NNG_EUNREACHABLE) return H3C_EUNREACHABLE; - if (c == NNG_ECONNSHUT) return H3C_ECONNSHUT; - return c ? H3C_EUNKNOWN : 0; -} diff --git a/h3client/nnge.h b/h3client/nnge.h deleted file mode 100644 index 835f0cf..0000000 --- a/h3client/nnge.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef NNGE_H -#define NNGE_H - -int h3client_nnge(int c); - -#endif diff --git a/h3client/parse.h b/h3client/parse.h new file mode 100644 index 0000000..46ef064 --- /dev/null +++ b/h3client/parse.h @@ -0,0 +1,63 @@ +#ifndef PARSE_H +#define PARSE_H + +#include "little_endian.h" +#include + +static inline uint32_t parse_uint32(unsigned char const x[4]) +{ + if (little_endian()) + { + return (uint32_t)x[0] << 24| + (uint32_t)x[1] << 16| + (uint32_t)x[2] << 8| + (uint32_t)x[3] << 0; + } + else + { + return (uint32_t)x[0] << 0| + (uint32_t)x[1] << 8| + (uint32_t)x[2] << 16| + (uint32_t)x[3] << 24; + } +} + +static inline uint64_t parse_uint64(unsigned char const x[8]) +{ + if (little_endian()) + { + return (uint64_t)x[0] << 56| + (uint64_t)x[1] << 48| + (uint64_t)x[2] << 40| + (uint64_t)x[3] << 32| + (uint64_t)x[4] << 24| + (uint64_t)x[5] << 16| + (uint64_t)x[6] << 8| + (uint64_t)x[7] << 0; + } + else + { + return (uint64_t)x[0] << 0| + (uint64_t)x[1] << 8| + (uint64_t)x[2] << 16| + (uint64_t)x[3] << 24| + (uint64_t)x[4] << 32| + (uint64_t)x[5] << 40| + (uint64_t)x[6] << 48| + (uint64_t)x[7] << 56; + } +} + +static inline float parse_float(unsigned char const x[4]) +{ + return (union {uint32_t u; float f;}){.u = parse_uint32(x)}.f; +} + +static inline double parse_double(unsigned char const x[8]) +{ + return (union {uint64_t u; double f;}){.u = parse_uint64(x)}.f; +} + +static inline uint8_t parse_flag(unsigned char const x[1]) { return x[0]; } + +#endif diff --git a/h3client/posix.h b/h3client/posix.h new file mode 100644 index 0000000..54b6bc4 --- /dev/null +++ b/h3client/posix.h @@ -0,0 +1,13 @@ +#ifndef POSIX_H +#define POSIX_H + +#include +#include + +static inline size_t posix_strnlen(char const *s, size_t n) +{ + const char *p = memchr(s, 0, n); + return p ? p - s : n; +} + +#endif diff --git a/h3client/read.h b/h3client/read.h deleted file mode 100644 index 31b62a6..0000000 --- a/h3client/read.h +++ /dev/null @@ -1,84 +0,0 @@ -#ifndef READ_H -#define READ_H - -#include "bsd.h" -#include "lio.h" -#include - -static inline int read_map(struct lio_reader *x, uint32_t *size) -{ - if (lio_free(x, lip_unpack_map(lio_read(x), size))) return 1; - return 0; -} - -static inline int read_array(struct lio_reader *x, uint32_t *size) -{ - if (lio_free(x, lip_unpack_array(lio_read(x), size))) return 1; - return 0; -} - -static inline int read_string(struct lio_reader *x, uint32_t *size) -{ - if (lio_free(x, lip_unpack_string(lio_read(x), size))) return 1; - return 0; -} - -static inline int read_cstring(struct lio_reader *x, uint32_t size, - char *string) -{ - uint32_t length = 0; - if (read_string(x, &length)) return 1; - if (length >= size) return 1; - if (lio_readb(x, length, (unsigned char *)string)) return 1; - string[length] = '\0'; - return 0; -} - -static inline int read_cstring2(struct lio_reader *f, char **str) -{ - unsigned size = 0; - if (read_string(f, &size)) return 0; - if (!(*str = bsd_reallocf(*str, size + 1))) return 0; - if (lio_readb(f, size, (unsigned char *)*str)) return 0; - (*str)[size] = '\0'; - return 0; -} - -static inline int read_f32(struct lio_reader *x, float *data) -{ - if (lio_free(x, lip_unpack_float(lio_read(x), data))) return 1; - return 0; -} - -static inline int read_f64(struct lio_reader *x, double *data) -{ - if (lio_free(x, lip_unpack_float(lio_read(x), data))) return 1; - return 0; -} - -static inline int read_unsigned(struct lio_reader *x, unsigned *data) -{ - if (lio_free(x, lip_unpack_int(lio_read(x), data))) return 1; - return 0; -} - -static inline int read_ulong(struct lio_reader *x, unsigned long *data) -{ - if (lio_free(x, lip_unpack_int(lio_read(x), data))) return 1; - return 0; -} - -static inline int read_bool(struct lio_reader *x, bool *data) -{ - if (lio_free(x, lip_unpack_bool(lio_read(x), data))) return 1; - return 0; -} - -#define read_int(buffer, data) \ - _Generic((data), unsigned *: read_unsigned, unsigned long *: read_ulong)( \ - buffer, data) - -#define read_float(buffer, data) \ - _Generic((data), float *: read_f32, double *: read_f64)(buffer, data) - -#endif diff --git a/h3client/sequences.h b/h3client/sequences.h new file mode 100644 index 0000000..791c4ec --- /dev/null +++ b/h3client/sequences.h @@ -0,0 +1,17 @@ +#ifndef SEQUENCES_H +#define SEQUENCES_H + +static char const good_sequence[] = + "MLRSLIWKRSQAYSSVVTMSSISQRGNERLLSEVAGSHSRDNKILVLGGNGYVGSHICKE" + "ALRQGFSVSSLSRSGRSSLHDSWVDDVTWHQGDLLSPDSLKPALEGITSVISCVGGFGSN" + "SQMVRINGTANINAVKAAAEQGVKRFVYISAADFGVINNLIRGYFEGKRATEAEILDKFG" + "NRGSVLRPGFIHGTRQVGSIKLPLSLIGAPLEMVLKLLPKEVTKIPVIGPLLIPPVNVKS" + "VAATAVKAAVDPEFASGVIDVYRILQHGH"; + +static char const bad_sequence[] = + "MLRSLIWRSQAYSSVVTMSSISQRGNERLLSEVAGSHSRDNKILVLGNGYVGSHICKE" + "SQMVRINGTANINAVKAAAEQGVKRFVYISADFGVINNLIRGYFEGKRATEAEILDKF" + "NRGSVLRPGFIHGTRQVGSIKLPLSLIGAPLMVLKLLPKEVTKIPVIGPLLIPPVNVS" + "TAATAVKAAVDPEFASGVIDVYRILQHGH"; + +#endif diff --git a/h3client/strerror.c b/h3client/strerror.c deleted file mode 100644 index 772f0fe..0000000 --- a/h3client/strerror.c +++ /dev/null @@ -1,34 +0,0 @@ -#include "array_size.h" -#include "h3c_errno.h" -#include "h3c_strerror.h" -#include - -static char const *msg[] = { - [H3C_EUNKNOWN] = "unknown error", - [H3C_EPARSE] = "parse error", - [H3C_EUNPACK] = "unpack failure", - [H3C_EPACK] = "pack failure", - [H3C_EUNEOF] = "unexpected end-of-file", - [H3C_EOUTRANGE] = "out-of-range integer", - [H3C_ETIMEDOUT] = "timed out", - [H3C_ECANCELED] = "operation was canceled", - [H3C_EADDRINVAL] = "invalid address", - [H3C_ECLOSED] = "operation was aborted", - [H3C_ECONNREFUSED] = "connection was refused", - [H3C_ECONNRESET] = "connection was reset", - [H3C_EINVAL] = "invalid value", - [H3C_ENOMEM] = "insufficient free memory", - [H3C_EPEERAUTH] = "authentication failure", - [H3C_EPROTO] = "protocol error occurred", - [H3C_EUNREACHABLE] = "address is not reachable", - [H3C_ECONNSHUT] = "remote peer shutdown after sending data", -}; - -char const *h3client_strerror(int errno) -{ - if (errno > 0 && errno < (int)array_size(msg)) return msg[errno]; - - static char unknown[32] = {0}; - snprintf(unknown, sizeof unknown, "unknown error #%d", errno); - return unknown; -} diff --git a/h3client/test_corrupt.c b/h3client/test_corrupt.c deleted file mode 100644 index 7ff7e83..0000000 --- a/h3client/test_corrupt.c +++ /dev/null @@ -1,42 +0,0 @@ -#include "aye.h" -#include "h3c_deadline.h" -#include "h3c_dialer.h" -#include "h3c_fini.h" -#include "h3c_result.h" -#include "h3c_stream.h" -#include "helper.h" -#include -#include - -#define PORT 51371 - -static char const cmd[] = "--hmmdb 1 --acc --cut_ga --hmmdb_ranges 0..4"; - -int main(void) -{ - aye_begin(); - atexit(h3client_fini); - - struct h3client_dialer *d = h3client_dialer_new("127.0.0.1", PORT); - aye(d); - aye(!h3client_dialer_dial(d, h3client_deadline(1000))); - - struct h3client_stream *s = h3client_dialer_stream(d); - - struct h3c_result *result = h3c_result_new(); - aye(result); - - long deadline = h3client_deadline(1000 * 5); - aye(!h3client_stream_put(s, cmd, corrupt->name, corrupt->seq, deadline)); - - h3client_stream_wait(s); - aye(!h3client_stream_pop(s, result)); - aye(result->errnum == 7); - aye(!strcmp(result->errstr, "Error parsing FASTA sequence")); - - h3c_result_del(result); - h3client_stream_del(s); - h3client_dialer_del(d); - - return aye_end(); -} diff --git a/h3client/test_h3client.c b/h3client/test_h3client.c new file mode 100644 index 0000000..1e13af1 --- /dev/null +++ b/h3client/test_h3client.c @@ -0,0 +1,78 @@ +#include "aye.h" +#include "h3c_socket.h" +#include "h3r_result.h" +#include "sequences.h" +#include +#include +#include + +#define IP "127.0.0.1" +#define PORT 51371 + +static long fletcher16(int fd, uint8_t *buf, size_t bufsize) +{ + ssize_t n = 0; + uint16_t sum1 = 0; + uint16_t sum2 = 0; + while ((n = read(fd, buf, bufsize)) > 0) + { + for (int i = 0; i < (int)n; ++i) + { + sum1 = (sum1 + buf[i]) % 255; + sum2 = (sum2 + sum1) % 255; + } + } + if (n < 0) + { + fprintf(stderr, "Hash failure (line %d)", __LINE__); + exit(1); + } + + return (sum2 << 8) | sum1; +} + +static long hash(char const *filepath) +{ + static uint8_t buffer[8 * 1024]; + int fd = open(filepath, O_RDONLY); + if (!fd) + { + fprintf(stderr, "Failed to open file (line %d): %s", __LINE__, filepath); + exit(1); + } + + long chk = fletcher16(fd, buffer, sizeof(buffer)); + + aye(!close(fd)); + return chk; +} + +int main(void) +{ + aye_begin(); + struct h3c_socket *x = h3c_socket_new(); + aye(x); + aye(!h3c_socket_dial(x, IP, PORT, 5)); + aye(!h3c_socket_warmup(x)); + + static char const cmd[] = "--hmmdb 1 --acc --cut_ga"; + aye(!h3c_socket_send(x, cmd, good_sequence)); + + struct h3r *result = h3r_new(); + aye(!h3c_socket_recv(x, result)); + + int file = open("h3result.mp", O_WRONLY | O_CREAT | O_TRUNC, 0644); + aye(file >= 0); + aye(!h3r_pack(result, file)); + aye(!close(file)); + + long h = hash("h3result.mp"); + printf("Hash: %ld\n", h); + fflush(stdout); + // aye(h == 19340L || h == 0L || h == 0L); + + aye(!h3c_socket_hangup(x)); + h3c_socket_del(x); + remove("h3result.mp"); + return aye_end(); +} diff --git a/h3client/test_multi.c b/h3client/test_multi.c deleted file mode 100644 index e9a4920..0000000 --- a/h3client/test_multi.c +++ /dev/null @@ -1,63 +0,0 @@ -#include "aye.h" -#include "h3c_deadline.h" -#include "h3c_dialer.h" -#include "h3c_fini.h" -#include "h3c_result.h" -#include "h3c_stream.h" -#include "h3r_result.h" -#include "helper.h" -#include -#include - -#define PORT 51371 - -static char const cmd[] = "--hmmdb 1 --acc --cut_ga --hmmdb_ranges 0..4"; - -static inline int near(double a, double b) -{ - static double const rel_tol = 1e-09; - if (a == b) return 1; - if (isinf(a) || isinf(b)) return 0; - double diff = fabs(b - a); - return (diff <= fabs(rel_tol * b)) || (diff <= fabs(rel_tol * a)); -} - -int main(void) -{ - aye_begin(); - atexit(h3client_fini); - - struct h3client_dialer *d = h3client_dialer_new("127.0.0.1", PORT); - aye(d); - aye(!h3client_dialer_dial(d, h3client_deadline(1000))); - - struct h3client_stream *s = h3client_dialer_stream(d); - - struct h3c_result *result = h3c_result_new(); - aye(result); - - long deadline = h3client_deadline(1000 * 5); - for (size_t i = 0; i < array_size(ross); ++i) - { - aye(!h3client_stream_put(s, cmd, ross[i].name, ross[i].seq, deadline)); - } - - for (size_t i = 0; i < array_size(ross); ++i) - { - h3client_stream_wait(s); - aye(!h3client_stream_pop(s, result)); - aye(!result->errnum); - aye(h3r_nhits(result->content) == ross[i].expect.nhits); - if (h3r_nhits(result->content) > 0) - { - double lev = h3r_hit_logevalue(result->content, 0); - aye(near(lev, ross[i].expect.ln_evalue)); - } - } - - h3c_result_del(result); - h3client_stream_del(s); - h3client_dialer_del(d); - - return aye_end(); -} diff --git a/h3client/test_single.c b/h3client/test_single.c deleted file mode 100644 index 7261a9d..0000000 --- a/h3client/test_single.c +++ /dev/null @@ -1,391 +0,0 @@ -#include "aye.h" -#include "h3c_deadline.h" -#include "h3c_dialer.h" -#include "h3c_errno.h" -#include "h3c_fini.h" -#include "h3c_result.h" -#include "h3c_stream.h" -#include "helper.h" -#include -#include -#include -#include -#include - -#define PORT 51371 -static char const cmd[] = "--hmmdb 1 --acc --cut_ga"; - -static inline int near(double a, double b) -{ - static double const rel_tol = 1e-09; - if (a == b) return 1; - if (isinf(a) || isinf(b)) return 0; - double diff = fabs(b - a); - return (diff <= fabs(rel_tol * b)) || (diff <= fabs(rel_tol * a)); -} - -static void test_connection_timedout(void); -static void test_open_close_connection(void); -static void test_request_timedout(void); -static void test_pack_result(void); -static void test_unpack_result(void); -static void test_print_targets(void); -static void test_print_domains(void); -static void test_print_targets_table(void); -static void test_print_domains_table(void); -static void test_reuse_results(void); -static void test_reuse_results_print(void); -static void test_reuse_connection(void); -static void test_result_api(void); - -int main(void) -{ - aye_begin(); - atexit(h3client_fini); - test_connection_timedout(); - test_open_close_connection(); - test_request_timedout(); - test_pack_result(); - test_unpack_result(); - test_print_targets(); - test_print_domains(); - test_print_targets_table(); - test_print_domains_table(); - test_reuse_results(); - test_reuse_results_print(); - test_reuse_connection(); - test_result_api(); - remove("h3result.mp"); - remove("targets.tbl"); - remove("targets.txt"); - remove("domains.tbl"); - remove("domains.txt"); - return aye_end(); -} - -static long earlier(void) { return h3client_deadline(-1); } -static long later(void) { return h3client_deadline(1000 * 5); } - -static long hash(char const *filepath); -static struct h3client_dialer *conn_new(void); -static struct h3client_stream *conn_dial(struct h3client_dialer *d, - long deadline); -static void conn_del(struct h3client_dialer *d); -static struct h3c_result *request(struct h3client_stream *s, char const *name, - char const *seq, long deadline); - -static void test_connection_timedout(void) -{ - struct h3client_dialer *d = conn_new(); - aye(h3client_dialer_dial(d, earlier()) == H3C_ETIMEDOUT); - conn_del(d); -} - -static void test_open_close_connection(void) -{ - struct h3client_dialer *d = conn_new(); - aye(!h3client_dialer_dial(d, later())); - h3client_dialer_del(d); -} - -static void test_request_timedout(void) -{ - struct h3client_dialer *d = conn_new(); - struct h3client_stream *s = conn_dial(d, later()); - - aye(!h3client_stream_put(s, cmd, ross[GOOD].name, ross[GOOD].seq, earlier())); - h3client_stream_wait(s); - struct h3c_result *result = h3c_result_new(); - aye(result); - aye(h3client_stream_pop(s, result) == H3C_ETIMEDOUT); - - h3c_result_del(result); - h3client_stream_del(s); - conn_del(d); -} - -static struct h3c_result *request_ross(void) -{ - struct h3client_dialer *d = conn_new(); - aye(d); - struct h3client_stream *s = conn_dial(d, later()); - aye(s); - struct h3c_result *r = request(s, ross[GOOD].name, ross[GOOD].seq, later()); - aye(r); - - h3client_stream_del(s); - conn_del(d); - return r; -} - -static void test_pack_result(void) -{ - struct h3c_result *result = request_ross(); - aye(result); - - int file = open("h3result.mp", O_WRONLY | O_CREAT | O_TRUNC, 0644); - aye(file >= 0); - aye(!h3r_pack(result->content, file)); - aye(!close(file)); - - long h = hash("h3result.mp"); - aye(h == 8392L || h == 38307 || h == 46156); - - h3c_result_del(result); -} - -static void test_unpack_result(void) -{ - struct h3c_result *result = request_ross(); - aye(result); - - int file = open("h3result.mp", O_WRONLY | O_CREAT | O_TRUNC, 0644); - aye(file >= 0); - aye(!h3r_pack(result->content, file)); - aye(!close(file)); - - long h = hash("h3result.mp"); - aye(h == 8392L || h == 38307 || h == 46156); - - file = open("h3result.mp", O_RDONLY); - aye(file >= 0); - aye(h3r_unpack(result->content, file) == 0); - aye(!close(file)); - - file = open("h3result.mp", O_RDONLY); - aye(file >= 0); - aye(!h3r_unpack(result->content, file)); - aye(!close(file)); - - h = hash("h3result.mp"); - aye(h == 8392L || h == 38307 || h == 46156); - - h3c_result_del(result); -} - -static void test_print_targets(void) -{ - struct h3c_result *result = request_ross(); - aye(result); - - int file = open("targets.txt", O_WRONLY | O_CREAT | O_TRUNC, 0644); - aye(file >= 0); - h3r_print_targets(result->content, file); - aye(!close(file)); - - aye(hash("targets.txt") == 57543L); - - h3c_result_del(result); -} - -static void test_print_domains(void) -{ - struct h3c_result *result = request_ross(); - aye(result); - - int file = open("domains.txt", O_WRONLY | O_CREAT | O_TRUNC, 0644); - aye(file >= 0); - h3r_print_domains(result->content, file); - aye(!close(file)); - - aye(hash("domains.txt") == 46469L); - - h3c_result_del(result); -} - -static void test_print_targets_table(void) -{ - struct h3c_result *result = request_ross(); - aye(result); - - int file = open("targets.tbl", O_WRONLY | O_CREAT | O_TRUNC, 0644); - aye(file >= 0); - h3r_print_targets_table(result->content, file); - aye(!close(file)); - - aye(hash("targets.tbl") == 34790L); - - h3c_result_del(result); -} - -static void test_print_domains_table(void) -{ - struct h3c_result *result = request_ross(); - aye(result); - - int file = open("domains.tbl", O_WRONLY | O_CREAT | O_TRUNC, 0644); - aye(file >= 0); - h3r_print_domains_table(result->content, file); - aye(!close(file)); - - aye(hash("domains.tbl") == 3913L); - - h3c_result_del(result); -} - -static void test_reuse_results(void) -{ - struct h3c_result *result = h3c_result_new(); - aye(result); - - struct h3client_dialer *d = conn_new(); - aye(!h3client_dialer_dial(d, later())); - - struct h3client_stream *s = h3client_dialer_stream(d); - - aye(!h3client_stream_put(s, cmd, ross[GOOD].name, ross[GOOD].seq, later())); - h3client_stream_wait(s); - aye(!h3client_stream_pop(s, result)); - - h3client_stream_del(s); - h3client_dialer_del(d); - - h3c_result_del(result); -} - -static void test_reuse_results_print(void) -{ - int64_t target = 57543L; - int64_t domain = 46469L; - - struct h3c_result *result = h3c_result_new(); - aye(result); - - struct h3client_dialer *d = conn_new(); - aye(!h3client_dialer_dial(d, later())); - - struct h3client_stream *s = h3client_dialer_stream(d); - - aye(!h3client_stream_put(s, cmd, ross[GOOD].name, ross[GOOD].seq, later())); - h3client_stream_wait(s); - aye(!h3client_stream_pop(s, result)); - - h3client_stream_del(s); - h3client_dialer_del(d); - - int file = open("targets.txt", O_WRONLY | O_CREAT | O_TRUNC, 0644); - aye(file >= 0); - h3r_print_targets(result->content, file); - aye(!close(file)); - aye(hash("targets.txt") == target); - - file = open("domains.txt", O_WRONLY | O_CREAT | O_TRUNC, 0644); - aye(file >= 0); - h3r_print_domains(result->content, file); - aye(!close(file)); - aye(hash("domains.txt") == domain); - - h3c_result_del(result); -} - -static void test_reuse_connection(void) -{ - struct h3c_result *result = h3c_result_new(); - aye(result); - - struct h3client_dialer *d = conn_new(); - aye(!h3client_dialer_dial(d, later())); - - struct h3client_stream *s = h3client_dialer_stream(d); - - aye(!h3client_stream_put(s, cmd, ross[GOOD].name, ross[GOOD].seq, later())); - h3client_stream_wait(s); - aye(!h3client_stream_pop(s, result)); - - aye(!h3client_stream_put(s, cmd, ross[BAD].name, ross[BAD].seq, later())); - h3client_stream_wait(s); - aye(!h3client_stream_pop(s, result)); - - h3client_stream_del(s); - h3client_dialer_del(d); - - h3c_result_del(result); -} - -static void test_result_api(void) -{ - struct h3c_result *result = request_ross(); - aye(result); - - char const *name[] = {"000000005", "000000003", "000000002", "000000004"}; - char const *acc[] = {"PF13460.8", "PF01370.23", "PF01073.21", "PF05368.15"}; - double eln[] = {-53.808984215028, -38.604817925966, -34.047928969184, - -31.743561848164}; - - aye(h3r_nhits(result->content) == 4); - aye(!result->errnum); - - for (int i = 0; i < 4; ++i) - { - aye(!strcmp(name[i], h3r_hit_name(result->content, i))); - aye(!strcmp(acc[i], h3r_hit_accession(result->content, i))); - aye(near(eln[i], h3r_hit_logevalue(result->content, i))); - } - - h3c_result_del(result); -} - -static struct h3client_dialer *conn_new(void) -{ - struct h3client_dialer *d = h3client_dialer_new("127.0.0.1", PORT); - aye(d); - return d; -} - -static struct h3client_stream *conn_dial(struct h3client_dialer *d, - long deadline) -{ - aye(!h3client_dialer_dial(d, deadline)); - return h3client_dialer_stream(d); -} - -static void conn_del(struct h3client_dialer *d) { h3client_dialer_del(d); } - -static struct h3c_result *request(struct h3client_stream *s, char const *name, - char const *seq, long deadline) -{ - aye(!h3client_stream_put(s, cmd, name, seq, deadline)); - h3client_stream_wait(s); - struct h3c_result *result = h3c_result_new(); - aye(result); - aye(!h3client_stream_pop(s, result)); - return result; -} - -static long fletcher16(int fd, uint8_t *buf, size_t bufsize) -{ - ssize_t n = 0; - uint16_t sum1 = 0; - uint16_t sum2 = 0; - while ((n = read(fd, buf, bufsize)) > 0) - { - for (int i = 0; i < (int)n; ++i) - { - sum1 = (sum1 + buf[i]) % 255; - sum2 = (sum2 + sum1) % 255; - } - } - if (n < 0) - { - fprintf(stderr, "Hash failure (line %d)", __LINE__); - exit(1); - } - - return (sum2 << 8) | sum1; -} - -static long hash(char const *filepath) -{ - static uint8_t buffer[8 * 1024]; - int fd = open(filepath, O_RDONLY); - if (!fd) - { - fprintf(stderr, "Failed to open file (line %d): %s", __LINE__, filepath); - exit(1); - } - - long chk = fletcher16(fd, buffer, sizeof(buffer)); - - aye(!close(fd)); - return chk; -} diff --git a/h3client/timeout.c b/h3client/timeout.c deleted file mode 100644 index 4908f52..0000000 --- a/h3client/timeout.c +++ /dev/null @@ -1,10 +0,0 @@ -#include "timeout.h" -#include "nng/nng.h" -#include "nng/supplemental/util/platform.h" - -int h3client_timeout(long deadline) -{ - long timeout = deadline - nng_clock(); - if (timeout < 0) timeout = 0; - return (int)timeout; -} diff --git a/h3client/timeout.h b/h3client/timeout.h deleted file mode 100644 index 1f5a15e..0000000 --- a/h3client/timeout.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef TIMEOUT_H -#define TIMEOUT_H - -int h3client_timeout(long deadline); - -#endif diff --git a/h3client/utils.c b/h3client/utils.c deleted file mode 100644 index 2c5fe26..0000000 --- a/h3client/utils.c +++ /dev/null @@ -1,140 +0,0 @@ -#include "utils.h" -#include "h3c_errno.h" -#include "zc.h" -#include -#include - -union num64 -{ - int64_t i; - uint64_t u; - double f; -}; - -union num32 -{ - int32_t i; - uint32_t u; - float f; -}; - -static union num64 eatnum64(unsigned char const **data) -{ - union num64 ui = {.u = 0}; - memcpy(&ui.u, *data, sizeof(ui.u)); - *data += sizeof(ui.u); - ui.u = zc_ntohll(ui.u); - return ui; -} - -static union num32 eatnum32(unsigned char const **data) -{ - union num32 ui = {.u = 0}; - memcpy(&ui.u, *data, sizeof(ui.u)); - *data += sizeof(ui.u); - ui.u = zc_ntohl(ui.u); - return ui; -} - -uint64_t h3client_eatu64(unsigned char const **data) -{ - return eatnum64(data).u; -} - -int64_t h3client_eati64(unsigned char const **data) { return eatnum64(data).i; } - -uint32_t h3client_eatu32(unsigned char const **data) -{ - return eatnum32(data).u; -} - -int32_t h3client_eati32(unsigned char const **data) { return eatnum32(data).i; } - -uint8_t h3client_eatu8(unsigned char const **data) -{ - uint8_t u8 = 0; - memcpy(&u8, *data, sizeof(u8)); - *data += sizeof(u8); - return u8; -} - -double h3client_eatf64(unsigned char const **data) { return eatnum64(data).f; } - -float h3client_eatf32(unsigned char const **data) { return eatnum32(data).f; } - -int h3client_eatstr(char **dst, unsigned char const **data) -{ - size_t size = strlen((char const *)*data) + 1; - if (!(*dst = zc_reallocf(*dst, size))) return H3C_ENOMEM; - memcpy(*dst, *data, size); - *data += size; - return 0; -} - -char *h3client_strskip(char **str) -{ - char *tmp = *str; - *str += strlen(*str) + 1; - return tmp; -} - -bool h3client_expect_n_strings(size_t size, char const *ptr, unsigned n) -{ - char const *end = ptr + size; - unsigned i = 0; - while (i < n && ptr < end) - { - while (ptr < end && *ptr) - ++ptr; - - if (ptr < end) ++i; - } - return i == n; -} - -// bool h3client_expect_key(struct lip_file *f, char const *key) -// { -// char str[16] = {0}; -// unsigned size = (unsigned)strlen(key) + 1; -// lip_read_cstr(f, size, str); -// -// return !lip_file_error(f) && strncmp(str, key, sizeof(str)) == 0; -// } -// -// bool h3client_expect_array_size(struct lip_file *f, unsigned size) -// { -// unsigned sz = 0; -// lip_read_array_size(f, &sz); -// return !lip_file_error(f) && size == sz; -// } -// -// bool h3client_expect_map_size(struct lip_file *f, unsigned size) -// { -// unsigned sz = 0; -// lip_read_map_size(f, &sz); -// return !lip_file_error(f) && size == sz; -// } -// -// int h3client_read_string(struct lip_file *f, char **str) -// { -// unsigned size = 0; -// if (!lip_read_str_size(f, &size)) return H3CLIENT_EUNPACK; -// if (!(*str = zc_reallocf(*str, size + 1))) return H3C_ENOMEM; -// if (!lip_read_str_data(f, size, *str)) return H3CLIENT_EUNPACK; -// (*str)[size] = 0; -// return 0; -// } - -char *h3client_strxdup(char *dst, char const *src) -{ - assert(dst != 0); - if (!src) - { - dst[0] = 0; - return dst; - } - - size_t sz = strlen(src); - void *t = zc_reallocf(dst, sz + 1); - return t ? memcpy(t, src, sz + 1) : 0; -} diff --git a/h3client/utils.h b/h3client/utils.h deleted file mode 100644 index 3843d83..0000000 --- a/h3client/utils.h +++ /dev/null @@ -1,47 +0,0 @@ -#ifndef UTILS_H -#define UTILS_H - -#include -#include -#include - -uint64_t h3client_eatu64(unsigned char const **data); -int64_t h3client_eati64(unsigned char const **data); - -uint32_t h3client_eatu32(unsigned char const **data); -int32_t h3client_eati32(unsigned char const **data); - -uint8_t h3client_eatu8(unsigned char const **data); - -double h3client_eatf64(unsigned char const **data); -float h3client_eatf32(unsigned char const **data); - -int h3client_eatstr(char **dst, unsigned char const **data); -char *h3client_strskip(char **str); - -#define ESCAPE_OVERRUN(rc, cur, end, sz) if (end < cur + sz) defer_return2(H3C_EPARSE) - -bool h3client_expect_n_strings(size_t size, char const *ptr, unsigned n); - -struct lip_file; - -bool h3client_expect_key(struct lip_file *f, char const *key); -bool h3client_expect_array_size(struct lip_file *f, unsigned size); -bool h3client_expect_map_size(struct lip_file *f, unsigned size); - -int h3client_read_string(struct lip_file *f, char **str); - -char *h3client_strxdup(char *dst, char const *src); - -#define MAX(a, b) (((a) > (b)) ? (a) : (b)) - -static inline unsigned zero_clip(int x) { return x > 0 ? (unsigned)x : 0; } - -#define DEL(ptr) \ - do \ - { \ - free((ptr)); \ - (ptr) = 0; \ - } while (0); - -#endif diff --git a/h3client/write.h b/h3client/write.h deleted file mode 100644 index 399875f..0000000 --- a/h3client/write.h +++ /dev/null @@ -1,45 +0,0 @@ -#ifndef WRITE_H -#define WRITE_H - -#include "lio.h" -#include - -static inline int write_cstring(struct lio_writer *x, char const *string) -{ - uint32_t length = (uint32_t)strlen(string); - if (lio_write(x, lip_pack_string(lio_alloc(x), length))) return 1; - if (lio_writeb(x, length, string)) return 1; - return 0; -} - -static inline int write_float(struct lio_writer *x, float data) -{ - if (lio_write(x, lip_pack_float(lio_alloc(x), data))) return 1; - return 0; -} - -static inline int write_int(struct lio_writer *x, int data) -{ - if (lio_write(x, lip_pack_int(lio_alloc(x), data))) return 1; - return 0; -} - -static inline int write_bool(struct lio_writer *x, bool data) -{ - if (lio_write(x, lip_pack_bool(lio_alloc(x), data))) return 1; - return 0; -} - -static inline int write_array(struct lio_writer *x, uint32_t size) -{ - if (lio_write(x, lip_pack_array(lio_alloc(x), size))) return 1; - return 0; -} - -static inline int write_map(struct lio_writer *x, uint32_t size) -{ - if (lio_write(x, lip_pack_map(lio_alloc(x), size))) return 1; - return 0; -} - -#endif diff --git a/h3client/zc.c b/h3client/zc.c deleted file mode 100644 index fbf36f3..0000000 --- a/h3client/zc.c +++ /dev/null @@ -1,104 +0,0 @@ -#include "zc.h" -#include -#include -#include -#include -#include - -static uint32_t zc_byteswap32(uint32_t x) -{ - return (uint32_t)(x >> 24 | (x >> 8 & 0xff00) | (x << 8 & 0xff0000) | - x << 24); -} - -static uint64_t zc_byteswap64(uint64_t x) -{ - return (uint64_t)((zc_byteswap32(x) + 0ULL) << 32 | zc_byteswap32(x >> 32)); -} - -enum -{ - ZC_ENDIAN_LITTLE = 1234, - ZC_ENDIAN_BIG = 4321, -}; - -#ifdef __STDC_ENDIAN_NATIVE__ -#if __STDC_ENDIAN_NATIVE__ == __STDC_ENDIAN_LITTLE__ -#define ZC_ENDIAN_NATIVE ZC_ENDIAN_LITTLE -#elif __STDC_ENDIAN_NATIVE__ == __STDC_ENDIAN_BIG__ -#define ZC_ENDIAN_NATIVE ZC_ENDIAN_BIG -#else -#error "Unknown native byte order" -#endif -#endif - -#ifdef ZC_ENDIAN_NATIVE - -#if ZC_ENDIAN_NATIVE == ZC_ENDIAN_LITTLE - -static uint32_t zc_htonl(uint32_t x) { return zc_byteswap32(x); } -static uint64_t zc_htonll(uint64_t x) { return zc_byteswap64(x); } - -uint32_t zc_ntohl(uint32_t x) { return zc_htonl(x); } -uint64_t zc_ntohll(uint64_t x) { return zc_htonll(x); } - -#else -static uint32_t zc_htonl(uint32_t x) { return x; } -static uint64_t zc_htonll(uint64_t x) { return x; } - -uint32_t zc_ntohl(uint32_t x) { return x; } -uint64_t zc_ntohll(uint64_t x) { return x; } -#endif - -#else - -static int zc_endianness(void) -{ - union - { - uint32_t value; - uint8_t data[sizeof(uint32_t)]; - } number; - - number.data[0] = 0x00; - number.data[1] = 0x01; - number.data[2] = 0x02; - number.data[3] = 0x03; - - switch (number.value) - { - case (uint32_t)(0x00010203): - return ZC_ENDIAN_BIG; - case (uint32_t)(0x03020100): - return ZC_ENDIAN_LITTLE; - default: - exit(1); - return -1; - } -} - -static uint32_t zc_htonl(uint32_t x) -{ - if (zc_endianness() == ZC_ENDIAN_BIG) return x; - return zc_byteswap32(x); -} - -static uint64_t zc_htonll(uint64_t x) -{ - if (zc_endianness() == ZC_ENDIAN_BIG) return x; - return zc_byteswap64(x); -} - -uint32_t zc_ntohl(uint32_t x) { return zc_htonl(x); } -uint64_t zc_ntohll(uint64_t x) { return zc_htonll(x); } - -#endif - -void *zc_reallocf(void *ptr, size_t size) -{ - assert(size > 0); - void *new_ptr = realloc(ptr, size); - - if (!new_ptr) free(ptr); - return new_ptr; -} diff --git a/h3client/zc.h b/h3client/zc.h deleted file mode 100644 index 557bb7a..0000000 --- a/h3client/zc.h +++ /dev/null @@ -1,118 +0,0 @@ -#ifndef ZC_H -#define ZC_H - -#include -#include -#include -#include - -#if SHRT_MAX == INT8_MAX -#define ZC_BYTES_PER_SHORT 1 -#define ZC_SHORT_WIDTH 8 -#elif SHRT_MAX == INT16_MAX -#define ZC_BYTES_PER_SHORT 2 -#define ZC_SHORT_WIDTH 16 -#elif SHRT_MAX == INT32_MAX -#define ZC_BYTES_PER_SHORT 4 -#define ZC_SHORT_WIDTH 32 -#elif SHRT_MAX == INT64_MAX -#define ZC_BYTES_PER_SHORT 8 -#define ZC_SHORT_WIDTH 64 -#else -#error "Cannot determine size of short" -#endif - -#if INT_MAX == INT8_MAX -#define ZC_BYTES_PER_INT 1 -#define ZC_INT_WIDTH 8 -#elif INT_MAX == INT16_MAX -#define ZC_BYTES_PER_INT 2 -#define ZC_INT_WIDTH 16 -#elif INT_MAX == INT32_MAX -#define ZC_BYTES_PER_INT 4 -#define ZC_INT_WIDTH 32 -#elif INT_MAX == INT64_MAX -#define ZC_BYTES_PER_INT 8 -#define ZC_INT_WIDTH 64 -#else -#error "Cannot determine size of int" -#endif - -#if LONG_MAX == INT8_MAX -#define ZC_BYTES_PER_LONG 1 -#define ZC_LONG_WIDTH 8 -#elif LONG_MAX == INT16_MAX -#define ZC_BYTES_PER_LONG 2 -#define ZC_LONG_WIDTH 16 -#elif LONG_MAX == INT32_MAX -#define ZC_BYTES_PER_LONG 4 -#define ZC_LONG_WIDTH 32 -#elif LONG_MAX == INT64_MAX -#define ZC_BYTES_PER_LONG 8 -#define ZC_LONG_WIDTH 64 -#else -#error "Cannot determine size of long" -#endif - -enum -{ - ZC_WINDOWS, - ZC_UNIX, - ZC_MACOS, -}; - -#if defined(_WIN16) || defined(_WIN32) || defined(_WIN64) || defined(__WIN32__) -#define ZC_OS ZS_WINDOWS -#elif defined(__unix__) || defined(__unix) -#define ZC_OS ZS_UNIX -#elif defined(__APPLE__) -#define ZC_OS ZC_MACOS -#endif - -#ifdef MS_WINDOWS -#define ZC_PATH_SEP '\\' -#endif - -#ifndef ZC_PATH_SEP -#define ZC_PATH_SEP '/' -#endif - -#define zc_array_size(arr) (sizeof(arr) / sizeof((arr)[0])) - -/** - * zc_container_of - cast a member of a structure out to the containing - * structure - * @ptr: the pointer to the member. - * @type: the type of the container struct this is embedded in. - * @member: the name of the member within the struct. - * - */ -#define zc_container_of(ptr, type, member) \ - ({ \ - char *__mptr = (char *)(ptr); \ - ((type *)(__mptr - offsetof(type, member))); \ - }) - -/** - * zc_container_of_safe - cast a member of a structure out to the containing - * structure - * @ptr: the pointer to the member. - * @type: the type of the container struct this is embedded in. - * @member: the name of the member within the struct. - * - * Return NULL if ptr is NULL. - */ -#define zc_container_of_safe(ptr, type, member) \ - ({ \ - char *__mptr = (char *)(ptr); \ - __mptr == NULL ? (type *)__mptr \ - : ((type *)(__mptr - offsetof(type, member))); \ - }) - -uint16_t zc_ntohs(uint16_t); -uint32_t zc_ntohl(uint32_t); -uint64_t zc_ntohll(uint64_t); - -void *zc_reallocf(void *ptr, size_t size); - -#endif diff --git a/h3client/zsetby.h b/h3client/zsetby.h deleted file mode 100644 index 80bc6de..0000000 --- a/h3client/zsetby.h +++ /dev/null @@ -1,11 +0,0 @@ -#ifndef ZSETBY_H -#define ZSETBY_H - -enum zsetby -{ - ZSETBY_NTARGETS = 0, - ZSETBY_OPTION = 1, - ZSETBY_FILEINFO = 2 -}; - -#endif