From 755bb33714d76e352817e16615b80be02354130f Mon Sep 17 00:00:00 2001 From: JeffBezanson Date: Sun, 17 Aug 2008 03:47:32 +0000 Subject: [PATCH] basic ios read, write, and stream creation --- llt/Makefile | 2 +- llt/cplxprint.c | 4 +- llt/ios.c | 173 +++++++++++++++++++++++++++++++++++++++++++++++- llt/ios.h | 26 ++++---- llt/unittest.c | 31 +++++++++ 5 files changed, 218 insertions(+), 18 deletions(-) diff --git a/llt/Makefile b/llt/Makefile index 71c1f36..4fc67ef 100644 --- a/llt/Makefile +++ b/llt/Makefile @@ -31,7 +31,7 @@ release: $(OBJS) test: make clean - make release CFLAGS=-DENABLE_LLT_TEST + make debug CFLAGS=-DENABLE_LLT_TEST gcc $(TESTSRC) $(TARGET) -o $(TESTER) -lm ./$(TESTER) diff --git a/llt/cplxprint.c b/llt/cplxprint.c index 9c11883..eb5d12d 100644 --- a/llt/cplxprint.c +++ b/llt/cplxprint.c @@ -46,14 +46,14 @@ void snprint_cplx(char *s, size_t cnt, double re, double im, if (!fzi) { len = sl = strlen(s); if (dbl_equals(im, -1)) { - while (len-sl < (size_t)width-2 && len < (space-3)) + while ((long)(len-sl) < (long)(width-2) && len < (space-3)) s[len++] = ' '; s[len] = '-'; s[len+1] = 'i'; s[len+2] = '\0'; } else if (dbl_equals(im, 1)) { - while (len-sl < (size_t)width-1 && len < (space-2)) + while ((long)(len-sl) < (long)(width-1) && len < (space-2)) s[len++] = ' '; s[len] = 'i'; s[len+1] = '\0'; diff --git a/llt/ios.c b/llt/ios.c index 0c5201e..19f7cf6 100644 --- a/llt/ios.c +++ b/llt/ios.c @@ -5,6 +5,7 @@ #include #include #include +#include // for printf #ifdef WIN32 #include @@ -15,6 +16,8 @@ #include #include #include +#include +#include #endif #include "dtypes.h" @@ -223,7 +226,7 @@ static size_t _writebuf_force(ios_t *s, char *data, size_t n) /* interface functions, low level */ -size_t ios_read(ios_t *s, char *dest, size_t n, int all) +static size_t _ios_read(ios_t *s, char *dest, size_t n, int all) { size_t tot = 0; size_t got, avail; @@ -289,12 +292,23 @@ size_t ios_read(ios_t *s, char *dest, size_t n, int all) return tot; } +size_t ios_read(ios_t *s, char *dest, size_t n) +{ + return _ios_read(s, dest, n, 0); +} + +size_t ios_readall(ios_t *s, char *dest, size_t n) +{ + return _ios_read(s, dest, n, 1); +} + size_t ios_write(ios_t *s, char *data, size_t n) { if (n == 0) return 0; size_t space; size_t wrote = 0; + if (s->state == bst_none) s->state = bst_wr; if (s->state == bst_wr) space = s->maxsize - s->bpos; else @@ -308,9 +322,21 @@ size_t ios_write(ios_t *s, char *data, size_t n) return wrote; } else if (n <= space) { + if (s->bm == bm_line) { + char *nl; + if ((nl=(char*)memrchr(data, '\n', n)) != NULL) { + size_t linesz = nl-data+1; + s->bm = bm_block; + wrote += ios_write(s, data, linesz); + ios_flush(s); + s->bm = bm_line; + n -= linesz; + data += linesz; + } + } memcpy(s->buf + s->bpos, data, n); s->bpos += n; - wrote = n; + wrote += n; } else { s->state = bst_wr; @@ -331,6 +357,13 @@ size_t ios_write(ios_t *s, char *data, size_t n) off_t ios_seek(ios_t *s, off_t pos) { s->_eof = 0; + if (s->bm == bm_mem) { + if ((size_t)pos > s->size) + return -1; + s->bpos = pos; + return s->bpos; + } + // TODO } off_t ios_seek_end(ios_t *s) @@ -548,21 +581,155 @@ int ios_copyall(ios_t *to, ios_t *from) return ios_copy_(to, from, 0, 1); } +static void _ios_init(ios_t *s) +{ + // put all fields in a sane initial state + s->bm = bm_block; + s->state = bst_none; + s->errcode = 0; + s->buf = NULL; + s->maxsize = 0; + s->size = 0; + s->bpos = 0; + s->ndirty = 0; + s->tally = 0; + s->fd = -1; + s->byteswap = 0; + s->ownbuf = 0; + s->ownfd = 0; + s->_eof = 0; + s->rereadable = 0; +} /* stream object initializers. we do no allocation. */ ios_t *ios_file(ios_t *s, char *fname, int create, int rewrite) { + int fd; + int flags = O_RDWR; + if (create) flags |= O_CREAT; + if (rewrite) flags |= O_TRUNC; + fd = open(fname, flags, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH/*644*/); + if (fd == -1) { + s->fd = -1; + return NULL; + } + s = ios_fd(s, fd, 1); + s->ownfd = 1; + return s; } ios_t *ios_mem(ios_t *s, size_t initsize) { + _ios_init(s); + s->bm = bm_mem; + _buf_realloc(s, initsize); + return s; } -ios_t *ios_fd(ios_t *s, long fd) +ios_t *ios_str(ios_t *s, char *str) { + size_t n = strlen(str); + if (ios_mem(s, n+1)==NULL) return NULL; + ios_write(s, str, n+1); + ios_seek(s, 0); + return s; } +ios_t *ios_fd(ios_t *s, long fd, int isfile) +{ + _ios_init(s); + s->fd = fd; + if (isfile) s->rereadable = 1; + _buf_init(s, bm_block); + s->ownfd = 0; + return s; +} + +ios_t *ios_stdin() +{ + static ios_t *_ios_stdin = NULL; + if (_ios_stdin == NULL) { + _ios_stdin = malloc(sizeof(ios_t)); + ios_fd(_ios_stdin, STDIN_FILENO, 0); + } + return _ios_stdin; +} + +ios_t *ios_stdout() +{ + static ios_t *_ios_stdout = NULL; + if (_ios_stdout == NULL) { + _ios_stdout = malloc(sizeof(ios_t)); + ios_fd(_ios_stdout, STDOUT_FILENO, 0); + _ios_stdout->bm = bm_line; + } + return _ios_stdout; +} + +ios_t *ios_stderr() +{ + static ios_t *_ios_stderr = NULL; + if (_ios_stderr == NULL) { + _ios_stderr = malloc(sizeof(ios_t)); + ios_fd(_ios_stderr, STDERR_FILENO, 0); + _ios_stderr->bm = bm_none; + } + return _ios_stderr; +} /* higher level interface */ +int ios_putc(int c, ios_t *s) +{ + char ch = (char)c; + + return (int)ios_write(s, &ch, 1); +} + +int ios_getc(ios_t *s) +{ + if (s->_eof) return IOS_EOF; + char ch; + size_t n = ios_read(s, &ch, 1); + if (n < 1) + return IOS_EOF; + return (int)ch; +} + +int ios_ungetc(int c, ios_t *s) +{ + if (s->state == bst_wr) + return IOS_EOF; + if (s->bpos > 0) { + s->bpos--; + s->buf[s->bpos] = (char)c; + return c; + } + if (s->size == s->maxsize) { + if (_buf_realloc(s, s->maxsize*2) == NULL) + return IOS_EOF; + } + memmove(s->buf + 1, s->buf, s->size); + s->buf[0] = (char)c; + s->size++; + return c; +} + +int ios_printf(ios_t *s, char *format, ...) +{ + char *str; + va_list args; + + va_start(args, format); + // TODO: avoid copy + int c = vasprintf(&str, format, args); + va_end(args); + + if (c == -1) return c; + + ios_write(s, str, c); + + free(str); + return c; +} diff --git a/llt/ios.h b/llt/ios.h index 83afcef..9feb13f 100644 --- a/llt/ios.h +++ b/llt/ios.h @@ -61,7 +61,8 @@ typedef struct { } ios_t; /* low-level interface functions */ -size_t ios_read(ios_t *s, char *dest, size_t n, int all); +size_t ios_read(ios_t *s, char *dest, size_t n); +size_t ios_readall(ios_t *s, char *dest, size_t n); size_t ios_write(ios_t *s, char *data, size_t n); off_t ios_seek(ios_t *s, off_t pos); // absolute seek off_t ios_seek_end(ios_t *s); @@ -87,8 +88,12 @@ int ios_copyall(ios_t *to, ios_t *from); /* stream creation */ ios_t *ios_file(ios_t *s, char *fname, int create, int rewrite); ios_t *ios_mem(ios_t *s, size_t initsize); -ios_t *ios_fd(ios_t *s, long fd); +ios_t *ios_str(ios_t *s, char *str); +ios_t *ios_fd(ios_t *s, long fd, int isfile); // todo: ios_socket +ios_t *ios_stdin(); +ios_t *ios_stdout(); +ios_t *ios_stderr(); /* high-level functions - output */ int ios_putnum(ios_t *s, char *data, uint32_t type); @@ -112,13 +117,13 @@ int ios_prevutf8(ios_t *s); /* stdio-style functions */ #define IOS_EOF (-1) -int ios_putc(ios_t *s, int c); +int ios_putc(int c, ios_t *s); //wint_t ios_putwc(ios_t *s, wchar_t wc); int ios_getc(ios_t *s); //wint_t ios_getwc(ios_t *s); -int ios_ungetc(ios_t *s, int c); +int ios_ungetc(int c, ios_t *s); //wint_t ios_ungetwc(ios_t *s, wint_t wc); -#define ios_puts(s, str) ios_write(s, str, strlen(str)) +#define ios_puts(str, s) ios_write(s, str, strlen(str)) /* With memory streams, mixed reads and writes are equivalent to performing @@ -164,21 +169,18 @@ int ios_ungetc(ios_t *s, int c); design points: - data-source independence, including memory streams - - support 64-bit and large files - - efficient, low-latency buffering - - unget - expose buffer to user, allow user-owned buffers - allow direct I/O, don't always go through buffer - buffer-internal seeking. makes seeking back 1-2 bytes very fast, and makes it possible for sockets where it otherwise wouldn't be - - special support for utf8 - tries to allow switching between reading and writing + - support 64-bit and large files + - efficient, low-latency buffering + - special support for utf8 - type-aware functions with byte-order swapping service - position counter for meaningful data offsets with sockets - note: - the current code needs to be mostly rewritten. the design should be - as follows: + theory of operation: the buffer is a view of part of a file/stream. you can seek, read, and write around in it as much as you like, as if it were just a string. diff --git a/llt/unittest.c b/llt/unittest.c index f12800f..54d4836 100644 --- a/llt/unittest.c +++ b/llt/unittest.c @@ -43,6 +43,8 @@ int main() printf("u8 took %.4f sec (%d)\n\n", clock_now()-t0, j); */ + test_ios(); + return 0; } @@ -111,3 +113,32 @@ void test_dblprint() prettyreal(DBL_EPSILON); } + +void test_ios() +{ + ios_t *out = ios_stdout(); + ios_t *in = ios_stdin(); + + ios_putc('a', out); + ios_putc('b', out); + ios_putc('\n', out); + + char c[80]; + size_t i=0; + ios_t sts; + ios_str(&sts, "Test string."); + c[i++] = ios_getc(&sts); + c[i++] = ios_getc(&sts); + c[i++] = ios_getc(&sts); + c[i++] = '\0'; + printf("got: \"%s\"\n", c); + + ios_t ms; + ios_mem(&ms, 10); + int j; + for(j=0; j < 16; j++) + ios_puts("passersby were amazed by the ", &ms); + size_t bs; + char *bigstr = ios_takebuf(&ms, &bs); + printf("got: \"%s\" (size %d)\n", bigstr, bs); +}