From 7f1b6ff70b97e424ce73314809838c7cd94f3ae7 Mon Sep 17 00:00:00 2001 From: Nicholas Noll Date: Wed, 22 Apr 2020 19:51:30 -0700 Subject: feat: interfaces of newick io more general. can now take arbitrary readers/writers --- Makefile | 2 +- include/libbio.h | 7 ++++--- include/libn.h | 4 ++-- sys/libbio/io/newick.c | 47 +++++++++++++++++++++++------------------------ sys/libbio/test.c | 47 +++++++++++++++++++++++++++++++++++++++++++++-- 5 files changed, 75 insertions(+), 32 deletions(-) diff --git a/Makefile b/Makefile index 13e8c14..3b58bea 100644 --- a/Makefile +++ b/Makefile @@ -11,7 +11,7 @@ LIB_DIR := lib OBJ_DIR := build # Flags, Libraries and Includes -CFLAGS := -g -fno-strict-aliasing -fwrapv -fms-extensions +CFLAGS := -g -fno-strict-aliasing -fwrapv -fms-extensions -Wno-microsoft-anon-tag AFLAGS := -f elf64 INCS := -I$(INC_DIR) ELIBS := diff --git a/include/libbio.h b/include/libbio.h index 9f54015..3cdab4e 100644 --- a/include/libbio.h +++ b/include/libbio.h @@ -25,16 +25,17 @@ typedef struct bio·Tree } bio·Tree; /* newick i/o */ -bio·Tree bio·readnewick(Stream *file, mem·Allocator heap); -error bio·writenewick(bio·Tree tree, Stream *out); +bio·Tree bio·readnewick(io·Peeker stream, mem·Allocator heap); +error bio·writenewick(bio·Tree tree, io·Putter out); // ----------------------------------------------------------------------- // Sequences +#if 0 typedef struct bio·FastaReader bio·FastaReader; /* fasta/q i/o */ bio·Seq *bio·newfastareader(Stream *file, mem·Allocator heap); bio·Seq *bio·readfasta(bio·FastaParser *p); error bio·writefasta(bio·Seq *seq, Stream *out); - +#endif diff --git a/include/libn.h b/include/libn.h index 67d131d..d2479e4 100644 --- a/include/libn.h +++ b/include/libn.h @@ -112,13 +112,13 @@ int io·seek(Stream *s, long off, enum SeekPos origin); typedef struct io·Reader { int (*read)(int n, void *buf); -}; +} io·Reader; typedef struct io·Peeker { byte (*get)(void); error (*unget)(byte); -}; +} io·Peeker; typedef struct io·FullReader { diff --git a/sys/libbio/io/newick.c b/sys/libbio/io/newick.c index 0004fac..82ea0d7 100644 --- a/sys/libbio/io/newick.c +++ b/sys/libbio/io/newick.c @@ -65,20 +65,20 @@ tokstr(struct Token tok) // TODO: Bounds checking on buffer static struct Token -lex(Stream *s) +lex(io·Peeker s) { byte *c; struct Token tok; static byte b[1024]; c = b; - *c = io·getbyte(s); + *c = s.get(); if (isspace(*c)) { while (isspace(*c)) { - *(++c) = io·getbyte(s); + *(++c) = s.get(); } - io·ungetbyte(s, *c); + s.unget(*c); Assert(c - b < 1024); *c = 0; @@ -101,11 +101,11 @@ lex(Stream *s) case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': while (isdigit(*c)) { - NUM: *(++c) = io·getbyte(s); + NUM: *(++c) = s.get(); } if (*c == '.') goto NUM; - io·ungetbyte(s, *c); + s.unget(*c); Assert(c - b < 1024); *c = 0; @@ -115,10 +115,10 @@ lex(Stream *s) default: while (isalnum(*c)) { - *(++c) = io·getbyte(s); + *(++c) = s.get(); } - io·ungetbyte(s, *c); + s.unget(*c); Assert(c - b < 1024); *c = '\0'; @@ -130,7 +130,7 @@ lex(Stream *s) static struct Token -lex_nospace(Stream *s) +lex_nospace(io·Peeker s) { struct Token tok; tok = lex(s); @@ -147,7 +147,7 @@ struct Parser bio·Node *root; struct Token tok; - Stream *file; + io·Peeker file; mem·Allocator heap; }; @@ -280,7 +280,7 @@ parse(struct Parser *p) break; case tok·semi: - io·ungetbyte(p->file, ';'); + p->file.unget(';'); if (p->lev) { errorf("format error: uneven number of parentheses found at ';'"); goto ERROR; @@ -307,7 +307,7 @@ ERROR: } bio·Tree -bio·readnewick(Stream *file, mem·Allocator heap) +bio·readnewick(io·Peeker stream, mem·Allocator heap) { error err; struct Parser p; @@ -317,7 +317,7 @@ bio·readnewick(Stream *file, mem·Allocator heap) .lev = 0, .root = nil, .tok = (struct Token){ 0 }, - .file = file, + .file = stream, .heap = heap, }; err = parse(&p); @@ -334,7 +334,7 @@ bio·readnewick(Stream *file, mem·Allocator heap) // Write error -dump(bio·Node *node, Stream *out) +dump(bio·Node *node, io·Putter out) { byte b[24]; @@ -343,36 +343,35 @@ dump(bio·Node *node, Stream *out) } bio·Node *child; if (node->nchild) { - io·putbyte(out, '('); + out.put('('); dump(node->child[0], out); for (child = node->child[1]; child != nil; child = child->sibling) { - io·putbyte(out, ','); + out.put(','); dump(child, out); } - io·putbyte(out, ')'); + out.put(')'); } if (node->name) { - io·putstring(out, node->name); + out.putstr(node->name); } if (node->parent) { - io·putbyte(out, ':'); + out.put(':'); snprintf(b, arrlen(b), "%f", node->dist); - io·putstring(out, b); + out.putstr(b); } return 0; } error -bio·writenewick(bio·Tree tree, Stream *out) +bio·writenewick(bio·Tree tree, io·Putter out) { dump(tree.root, out); - io·putbyte(out, ';'); - io·putbyte(out, '\n'); - io·flush(out); + out.put(';'); + out.put('\n'); return 0; } diff --git a/sys/libbio/test.c b/sys/libbio/test.c index 18bb993..3941290 100644 --- a/sys/libbio/test.c +++ b/sys/libbio/test.c @@ -33,6 +33,45 @@ bio·free(void *ptr) static mem·Allocator arena = {.alloc = &bio·alloc, .realloc = &bio·realloc, .free = &bio·free }; +// ----------------------------------------------------------------------- +// Read/writer + +static Stream* INPUT; + +static +byte +get() +{ + return io·getbyte(INPUT); +} + +static +error +unget(byte c) +{ + return io·ungetbyte(INPUT, c); +} + +static io·Peeker peeker = {.get = &get, .unget = &unget}; + +static Stream* OUTPUT; + +static +error +put(byte b) +{ + return io·putbyte(OUTPUT, b); +} + +static +int +putstr(string s) +{ + return io·putstring(OUTPUT, s); +} + +static io·Putter putter = {.put = &put, .putstr = &putstr}; + // ----------------------------------------------------------------------- // Point of entry for testing @@ -54,11 +93,15 @@ main() fd[0] = io·open("/home/nolln/root/data/test/example.nwk", "r"); fd[1] = io·open("/home/nolln/root/data/test/example.proc.nwk", "w"); + INPUT = fd[0]; + OUTPUT = fd[1]; + printf("starting\n"); - t = bio·readnewick(fd[0], arena); - err = bio·writenewick(t, fd[1]); + t = bio·readnewick(peeker, arena); + err = bio·writenewick(t, putter); printf("ending\n"); + io·flush(fd[1]); io·close(fd[0]); io·close(fd[1]); return 0; } -- cgit v1.2.1