basic ios read, write, and stream creation

This commit is contained in:
JeffBezanson 2008-08-17 03:47:32 +00:00
parent fa0e134dd8
commit 755bb33714
5 changed files with 218 additions and 18 deletions

View File

@ -31,7 +31,7 @@ release: $(OBJS)
test: test:
make clean make clean
make release CFLAGS=-DENABLE_LLT_TEST make debug CFLAGS=-DENABLE_LLT_TEST
gcc $(TESTSRC) $(TARGET) -o $(TESTER) -lm gcc $(TESTSRC) $(TARGET) -o $(TESTER) -lm
./$(TESTER) ./$(TESTER)

View File

@ -46,14 +46,14 @@ void snprint_cplx(char *s, size_t cnt, double re, double im,
if (!fzi) { if (!fzi) {
len = sl = strlen(s); len = sl = strlen(s);
if (dbl_equals(im, -1)) { 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] = '-'; s[len] = '-';
s[len+1] = 'i'; s[len+1] = 'i';
s[len+2] = '\0'; s[len+2] = '\0';
} }
else if (dbl_equals(im, 1)) { 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++] = ' ';
s[len] = 'i'; s[len] = 'i';
s[len+1] = '\0'; s[len+1] = '\0';

173
llt/ios.c
View File

@ -5,6 +5,7 @@
#include <limits.h> #include <limits.h>
#include <errno.h> #include <errno.h>
#include <wchar.h> #include <wchar.h>
#include <stdio.h> // for printf
#ifdef WIN32 #ifdef WIN32
#include <malloc.h> #include <malloc.h>
@ -15,6 +16,8 @@
#include <unistd.h> #include <unistd.h>
#include <sys/time.h> #include <sys/time.h>
#include <sys/select.h> #include <sys/select.h>
#include <sys/stat.h>
#include <fcntl.h>
#endif #endif
#include "dtypes.h" #include "dtypes.h"
@ -223,7 +226,7 @@ static size_t _writebuf_force(ios_t *s, char *data, size_t n)
/* interface functions, low level */ /* 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 tot = 0;
size_t got, avail; size_t got, avail;
@ -289,12 +292,23 @@ size_t ios_read(ios_t *s, char *dest, size_t n, int all)
return tot; 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) size_t ios_write(ios_t *s, char *data, size_t n)
{ {
if (n == 0) return 0; if (n == 0) return 0;
size_t space; size_t space;
size_t wrote = 0; size_t wrote = 0;
if (s->state == bst_none) s->state = bst_wr;
if (s->state == bst_wr) if (s->state == bst_wr)
space = s->maxsize - s->bpos; space = s->maxsize - s->bpos;
else else
@ -308,9 +322,21 @@ size_t ios_write(ios_t *s, char *data, size_t n)
return wrote; return wrote;
} }
else if (n <= space) { 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); memcpy(s->buf + s->bpos, data, n);
s->bpos += n; s->bpos += n;
wrote = n; wrote += n;
} }
else { else {
s->state = bst_wr; 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) off_t ios_seek(ios_t *s, off_t pos)
{ {
s->_eof = 0; 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) 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); 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. */ /* stream object initializers. we do no allocation. */
ios_t *ios_file(ios_t *s, char *fname, int create, int rewrite) 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_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 */ /* 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;
}

View File

@ -61,7 +61,8 @@ typedef struct {
} ios_t; } ios_t;
/* low-level interface functions */ /* 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); 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(ios_t *s, off_t pos); // absolute seek
off_t ios_seek_end(ios_t *s); off_t ios_seek_end(ios_t *s);
@ -87,8 +88,12 @@ int ios_copyall(ios_t *to, ios_t *from);
/* stream creation */ /* stream creation */
ios_t *ios_file(ios_t *s, char *fname, int create, int rewrite); 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_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 // todo: ios_socket
ios_t *ios_stdin();
ios_t *ios_stdout();
ios_t *ios_stderr();
/* high-level functions - output */ /* high-level functions - output */
int ios_putnum(ios_t *s, char *data, uint32_t type); int ios_putnum(ios_t *s, char *data, uint32_t type);
@ -112,13 +117,13 @@ int ios_prevutf8(ios_t *s);
/* stdio-style functions */ /* stdio-style functions */
#define IOS_EOF (-1) #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); //wint_t ios_putwc(ios_t *s, wchar_t wc);
int ios_getc(ios_t *s); int ios_getc(ios_t *s);
//wint_t ios_getwc(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); //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 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: design points:
- data-source independence, including memory streams - 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 - expose buffer to user, allow user-owned buffers
- allow direct I/O, don't always go through buffer - allow direct I/O, don't always go through buffer
- buffer-internal seeking. makes seeking back 1-2 bytes very fast, - buffer-internal seeking. makes seeking back 1-2 bytes very fast,
and makes it possible for sockets where it otherwise wouldn't be and makes it possible for sockets where it otherwise wouldn't be
- special support for utf8
- tries to allow switching between reading and writing - 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 - type-aware functions with byte-order swapping service
- position counter for meaningful data offsets with sockets - position counter for meaningful data offsets with sockets
note: theory of operation:
the current code needs to be mostly rewritten. the design should be
as follows:
the buffer is a view of part of a file/stream. you can seek, read, and 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. write around in it as much as you like, as if it were just a string.

View File

@ -43,6 +43,8 @@ int main()
printf("u8 took %.4f sec (%d)\n\n", clock_now()-t0, j); printf("u8 took %.4f sec (%d)\n\n", clock_now()-t0, j);
*/ */
test_ios();
return 0; return 0;
} }
@ -111,3 +113,32 @@ void test_dblprint()
prettyreal(DBL_EPSILON); 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);
}