some fixes to ios
This commit is contained in:
parent
3d25a1a672
commit
21dd640454
186
llt/ios.c
186
llt/ios.c
|
@ -45,20 +45,6 @@ void *memrchr(const void *s, int c, size_t n)
|
|||
extern void *memrchr(const void *s, int c, size_t n);
|
||||
#endif
|
||||
|
||||
static int _fd_available(long fd)
|
||||
{
|
||||
#ifndef WIN32
|
||||
fd_set set;
|
||||
struct timeval tv = {0, 0};
|
||||
|
||||
FD_ZERO(&set);
|
||||
FD_SET(fd, &set);
|
||||
return (select(fd+1, &set, NULL, NULL, &tv)!=0);
|
||||
#else
|
||||
return 1;
|
||||
#endif
|
||||
}
|
||||
|
||||
// poll for read, unless forwrite!=0
|
||||
static void _fd_poll(long fd, int forwrite)
|
||||
{
|
||||
|
@ -115,10 +101,8 @@ static int _os_read_all(long fd, void *buf, size_t n, size_t *nread)
|
|||
n -= got;
|
||||
*nread += got;
|
||||
buf += got;
|
||||
if (err)
|
||||
if (err || got==0)
|
||||
return err;
|
||||
if (got == 0)
|
||||
_fd_poll(fd, 0);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
@ -155,8 +139,6 @@ static int _os_write_all(long fd, void *buf, size_t n, size_t *nwritten)
|
|||
buf += wrote;
|
||||
if (err)
|
||||
return err;
|
||||
if (wrote == 0)
|
||||
_fd_poll(fd, 1);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
@ -274,6 +256,7 @@ static size_t _ios_read(ios_t *s, char *dest, size_t n, int all)
|
|||
s->bpos = s->size = 0;
|
||||
s->state = bst_rd;
|
||||
|
||||
s->fpos = -1;
|
||||
if (n > MOST_OF(s->maxsize)) {
|
||||
// doesn't fit comfortably in buffer; go direct
|
||||
if (all)
|
||||
|
@ -281,7 +264,7 @@ static size_t _ios_read(ios_t *s, char *dest, size_t n, int all)
|
|||
else
|
||||
result = _os_read(s->fd, dest, n, &got);
|
||||
tot += got;
|
||||
if (got < n)
|
||||
if (got == 0)
|
||||
s->_eof = 1;
|
||||
return tot;
|
||||
}
|
||||
|
@ -292,13 +275,8 @@ static size_t _ios_read(ios_t *s, char *dest, size_t n, int all)
|
|||
return tot;
|
||||
}
|
||||
if (got == 0) {
|
||||
if (all) {
|
||||
_fd_poll(s->fd, 0);
|
||||
}
|
||||
else {
|
||||
s->_eof = 1;
|
||||
return tot;
|
||||
}
|
||||
s->_eof = 1;
|
||||
return tot;
|
||||
}
|
||||
s->size = got;
|
||||
}
|
||||
|
@ -377,6 +355,7 @@ size_t ios_write(ios_t *s, char *data, size_t n)
|
|||
wrote = _write_grow(s, data, n);
|
||||
}
|
||||
else if (s->bm == bm_none) {
|
||||
s->fpos = -1;
|
||||
_os_write_all(s->fd, data, n, &wrote);
|
||||
return wrote;
|
||||
}
|
||||
|
@ -417,24 +396,67 @@ off_t ios_seek(ios_t *s, off_t pos)
|
|||
if ((size_t)pos > s->size)
|
||||
return -1;
|
||||
s->bpos = pos;
|
||||
return s->bpos;
|
||||
}
|
||||
// TODO
|
||||
else {
|
||||
ios_flush(s);
|
||||
off_t fdpos = lseek(s->fd, pos, SEEK_SET);
|
||||
if (fdpos == (off_t)-1)
|
||||
return fdpos;
|
||||
s->bpos = s->size = 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
off_t ios_seek_end(ios_t *s)
|
||||
{
|
||||
s->_eof = 1;
|
||||
// TODO
|
||||
if (s->bm == bm_mem) {
|
||||
s->bpos = s->size;
|
||||
}
|
||||
else {
|
||||
ios_flush(s);
|
||||
off_t fdpos = lseek(s->fd, 0, SEEK_END);
|
||||
if (fdpos == (off_t)-1)
|
||||
return fdpos;
|
||||
s->bpos = s->size = 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
off_t ios_skip(ios_t *s, off_t offs)
|
||||
{
|
||||
if (offs < 0)
|
||||
if (offs != 0) {
|
||||
if (offs > 0) {
|
||||
if (offs <= (off_t)(s->size-s->bpos)) {
|
||||
s->bpos += offs;
|
||||
return 0;
|
||||
}
|
||||
else if (s->bm == bm_mem) {
|
||||
// TODO: maybe grow buffer
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else if (offs < 0) {
|
||||
if (-offs <= (off_t)s->bpos) {
|
||||
s->bpos += offs;
|
||||
s->_eof = 0;
|
||||
return 0;
|
||||
}
|
||||
else if (s->bm == bm_mem) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
ios_flush(s);
|
||||
if (s->state == bst_wr)
|
||||
offs += s->bpos;
|
||||
else if (s->state == bst_rd)
|
||||
offs -= (s->size - s->bpos);
|
||||
off_t fdpos = lseek(s->fd, offs, SEEK_CUR);
|
||||
if (fdpos == (off_t)-1)
|
||||
return fdpos;
|
||||
s->bpos = s->size = 0;
|
||||
s->_eof = 0;
|
||||
// TODO
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -443,9 +465,13 @@ off_t ios_pos(ios_t *s)
|
|||
if (s->bm == bm_mem)
|
||||
return (off_t)s->bpos;
|
||||
|
||||
off_t fdpos = lseek(s->fd, 0, SEEK_CUR);
|
||||
if (fdpos == (off_t)-1)
|
||||
return fdpos;
|
||||
off_t fdpos = s->fpos;
|
||||
if (fdpos == (off_t)-1) {
|
||||
fdpos = lseek(s->fd, 0, SEEK_CUR);
|
||||
if (fdpos == (off_t)-1)
|
||||
return fdpos;
|
||||
s->fpos = fdpos;
|
||||
}
|
||||
|
||||
if (s->state == bst_wr)
|
||||
fdpos += s->bpos;
|
||||
|
@ -483,30 +509,6 @@ int ios_eof(ios_t *s)
|
|||
if (s->_eof)
|
||||
return 1;
|
||||
return 0;
|
||||
/*
|
||||
if (_fd_available(s->fd))
|
||||
return 0;
|
||||
s->_eof = 1;
|
||||
return 1;
|
||||
*/
|
||||
}
|
||||
|
||||
static void _discard_partial_buffer(ios_t *s)
|
||||
{
|
||||
// this function preserves the invariant that data to write
|
||||
// begins at the beginning of the buffer, and s->size refers
|
||||
// to how much valid file data is stored in the buffer.
|
||||
|
||||
// this needs to be called when normal operation is interrupted in
|
||||
// the middle of the buffer. "normal operation" is reading or
|
||||
// writing to the end of the buffer. this happens e.g. when flushing.
|
||||
size_t delta = 0;
|
||||
if (s->ndirty && s->size > s->ndirty) {
|
||||
delta = s->size - s->ndirty;
|
||||
memmove(s->buf, s->buf + s->ndirty, delta);
|
||||
}
|
||||
s->size -= s->ndirty;
|
||||
s->bpos -= s->ndirty;
|
||||
}
|
||||
|
||||
int ios_flush(ios_t *s)
|
||||
|
@ -522,6 +524,7 @@ int ios_flush(ios_t *s)
|
|||
}
|
||||
|
||||
size_t nw, ntowrite=s->ndirty;
|
||||
s->fpos = -1;
|
||||
int err = _os_write_all(s->fd, s->buf, ntowrite, &nw);
|
||||
// todo: try recovering from some kinds of errors (e.g. retry)
|
||||
|
||||
|
@ -533,12 +536,17 @@ int ios_flush(ios_t *s)
|
|||
if (s->bpos != nw &&
|
||||
lseek(s->fd, (off_t)s->bpos - (off_t)nw, SEEK_CUR) == (off_t)-1) {
|
||||
}
|
||||
// now preserve the invariant that data to write
|
||||
// begins at the beginning of the buffer, and s->size refers
|
||||
// to how much valid file data is stored in the buffer.
|
||||
if (s->size > s->ndirty) {
|
||||
size_t delta = s->size - s->ndirty;
|
||||
memmove(s->buf, s->buf + s->ndirty, delta);
|
||||
}
|
||||
s->size -= s->ndirty;
|
||||
s->bpos = 0;
|
||||
}
|
||||
|
||||
if (s->ndirty <= s->bpos) {
|
||||
// in this case assume we're done with the first part of the buffer
|
||||
_discard_partial_buffer(s);
|
||||
}
|
||||
s->ndirty = 0;
|
||||
|
||||
if (err)
|
||||
|
@ -639,11 +647,6 @@ void ios_set_readonly(ios_t *s)
|
|||
s->readonly = 1;
|
||||
}
|
||||
|
||||
void ios_bswap(ios_t *s, int bswap)
|
||||
{
|
||||
s->byteswap = !!bswap;
|
||||
}
|
||||
|
||||
static size_t ios_copy_(ios_t *to, ios_t *from, size_t nbytes, bool_t all)
|
||||
{
|
||||
size_t total = 0, avail;
|
||||
|
@ -686,16 +689,21 @@ size_t ios_copyall(ios_t *to, ios_t *from)
|
|||
|
||||
size_t ios_copyuntil(ios_t *to, ios_t *from, char delim)
|
||||
{
|
||||
size_t total = 0, avail;
|
||||
size_t total = 0, avail=from->size - from->bpos;
|
||||
int first = 1;
|
||||
if (!ios_eof(from)) {
|
||||
do {
|
||||
avail = ios_readprep(from, LINE_CHUNK_SIZE);
|
||||
if (avail == 0) {
|
||||
first = 0;
|
||||
avail = ios_readprep(from, LINE_CHUNK_SIZE);
|
||||
}
|
||||
size_t written;
|
||||
char *pd = (char*)memchr(from->buf+from->bpos, delim, avail);
|
||||
if (pd == NULL) {
|
||||
written = ios_write(to, from->buf+from->bpos, avail);
|
||||
from->bpos += avail;
|
||||
total += written;
|
||||
avail = 0;
|
||||
}
|
||||
else {
|
||||
size_t ntowrite = pd - (from->buf+from->bpos) + 1;
|
||||
|
@ -704,7 +712,7 @@ size_t ios_copyuntil(ios_t *to, ios_t *from, char delim)
|
|||
total += written;
|
||||
return total;
|
||||
}
|
||||
} while (!ios_eof(from) && avail >= LINE_CHUNK_SIZE);
|
||||
} while (!ios_eof(from) && (first || avail >= LINE_CHUNK_SIZE));
|
||||
}
|
||||
from->_eof = 1;
|
||||
return total;
|
||||
|
@ -721,9 +729,9 @@ static void _ios_init(ios_t *s)
|
|||
s->size = 0;
|
||||
s->bpos = 0;
|
||||
s->ndirty = 0;
|
||||
s->tally = 0;
|
||||
s->fpos = -1;
|
||||
s->lineno = 1;
|
||||
s->fd = -1;
|
||||
s->byteswap = 0;
|
||||
s->ownbuf = 1;
|
||||
s->ownfd = 0;
|
||||
s->_eof = 0;
|
||||
|
@ -745,8 +753,7 @@ ios_t *ios_file(ios_t *s, char *fname, int rd, int wr, int create, int trunc)
|
|||
fd = open(fname, flags, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH/*644*/);
|
||||
if (fd == -1)
|
||||
goto open_file_err;
|
||||
s = ios_fd(s, fd, 1);
|
||||
s->ownfd = 1;
|
||||
s = ios_fd(s, fd, 1, 1);
|
||||
if (!wr)
|
||||
s->readonly = 1;
|
||||
return s;
|
||||
|
@ -781,13 +788,15 @@ ios_t *ios_static_buffer(ios_t *s, char *buf, size_t sz)
|
|||
return s;
|
||||
}
|
||||
|
||||
ios_t *ios_fd(ios_t *s, long fd, int isfile)
|
||||
ios_t *ios_fd(ios_t *s, long fd, int isfile, int own)
|
||||
{
|
||||
_ios_init(s);
|
||||
s->fd = fd;
|
||||
if (isfile) s->rereadable = 1;
|
||||
_buf_init(s, bm_block);
|
||||
s->ownfd = 0;
|
||||
s->ownfd = own;
|
||||
if (fd == STDERR_FILENO)
|
||||
s->bm = bm_none;
|
||||
return s;
|
||||
}
|
||||
|
||||
|
@ -798,14 +807,14 @@ ios_t *ios_stderr = NULL;
|
|||
void ios_init_stdstreams()
|
||||
{
|
||||
ios_stdin = LLT_ALLOC(sizeof(ios_t));
|
||||
ios_fd(ios_stdin, STDIN_FILENO, 0);
|
||||
ios_fd(ios_stdin, STDIN_FILENO, 0, 0);
|
||||
|
||||
ios_stdout = LLT_ALLOC(sizeof(ios_t));
|
||||
ios_fd(ios_stdout, STDOUT_FILENO, 0);
|
||||
ios_fd(ios_stdout, STDOUT_FILENO, 0, 0);
|
||||
ios_stdout->bm = bm_line;
|
||||
|
||||
ios_stderr = LLT_ALLOC(sizeof(ios_t));
|
||||
ios_fd(ios_stderr, STDERR_FILENO, 0);
|
||||
ios_fd(ios_stderr, STDERR_FILENO, 0, 0);
|
||||
ios_stderr->bm = bm_none;
|
||||
}
|
||||
|
||||
|
@ -836,6 +845,7 @@ int ios_getc(ios_t *s)
|
|||
if (ios_read(s, &ch, 1) < 1)
|
||||
return IOS_EOF;
|
||||
}
|
||||
if (ch == '\n') s->lineno++;
|
||||
return (unsigned char)ch;
|
||||
}
|
||||
|
||||
|
@ -935,18 +945,30 @@ void ios_purge(ios_t *s)
|
|||
}
|
||||
}
|
||||
|
||||
char *ios_readline(ios_t *s)
|
||||
{
|
||||
ios_t dest;
|
||||
ios_mem(&dest, 0);
|
||||
ios_copyuntil(&dest, s, '\n');
|
||||
size_t n;
|
||||
return ios_takebuf(&dest, &n);
|
||||
}
|
||||
|
||||
int vasprintf(char **strp, const char *fmt, va_list ap);
|
||||
|
||||
int ios_vprintf(ios_t *s, const char *format, va_list args)
|
||||
{
|
||||
char *str=NULL;
|
||||
int c;
|
||||
va_list al;
|
||||
va_copy(al, args);
|
||||
|
||||
if (s->state == bst_wr && s->bpos < s->maxsize && s->bm != bm_none) {
|
||||
size_t avail = s->maxsize - s->bpos;
|
||||
char *start = s->buf + s->bpos;
|
||||
c = vsnprintf(start, avail, format, args);
|
||||
if (c < 0) {
|
||||
va_end(al);
|
||||
return c;
|
||||
}
|
||||
if (c < avail) {
|
||||
|
@ -955,16 +977,18 @@ int ios_vprintf(ios_t *s, const char *format, va_list args)
|
|||
// TODO: only works right if newline is at end
|
||||
if (s->bm == bm_line && memrchr(start, '\n', (size_t)c))
|
||||
ios_flush(s);
|
||||
va_end(al);
|
||||
return c;
|
||||
}
|
||||
}
|
||||
c = vasprintf(&str, format, args);
|
||||
c = vasprintf(&str, format, al);
|
||||
|
||||
if (c >= 0) {
|
||||
ios_write(s, str, c);
|
||||
|
||||
LLT_FREE(str);
|
||||
}
|
||||
va_end(al);
|
||||
return c;
|
||||
}
|
||||
|
||||
|
|
14
llt/ios.h
14
llt/ios.h
|
@ -11,7 +11,7 @@ typedef enum { bm_none, bm_line, bm_block, bm_mem } bufmode_t;
|
|||
typedef enum { bst_none, bst_rd, bst_wr } bufstate_t;
|
||||
|
||||
#define IOS_INLSIZE 54
|
||||
#define IOS_BUFSIZE 8191
|
||||
#define IOS_BUFSIZE 131072
|
||||
|
||||
typedef struct {
|
||||
bufmode_t bm;
|
||||
|
@ -29,17 +29,13 @@ typedef struct {
|
|||
size_t bpos; // current position in buffer
|
||||
size_t ndirty; // # bytes at &buf[0] that need to be written
|
||||
|
||||
// this is a public field that keeps a running count of bytes
|
||||
// read or written. you can freely use and change it. this is
|
||||
// intended for keeping track of relative positions in streams
|
||||
// that don't have absolute positions (like sockets).
|
||||
size_t tally;
|
||||
off_t fpos; // cached file pos
|
||||
size_t lineno; // current line number
|
||||
|
||||
// pointer-size integer to support platforms where it might have
|
||||
// to be a pointer
|
||||
long fd;
|
||||
|
||||
unsigned char byteswap:1;
|
||||
unsigned char readonly:1;
|
||||
unsigned char ownbuf:1;
|
||||
unsigned char ownfd:1;
|
||||
|
@ -79,7 +75,6 @@ char *ios_takebuf(ios_t *s, size_t *psize); // release buffer to caller
|
|||
int ios_setbuf(ios_t *s, char *buf, size_t size, int own);
|
||||
int ios_bufmode(ios_t *s, bufmode_t mode);
|
||||
void ios_set_readonly(ios_t *s);
|
||||
void ios_bswap(ios_t *s, int bswap);
|
||||
size_t ios_copy(ios_t *to, ios_t *from, size_t nbytes);
|
||||
size_t ios_copyall(ios_t *to, ios_t *from);
|
||||
size_t ios_copyuntil(ios_t *to, ios_t *from, char delim);
|
||||
|
@ -94,7 +89,7 @@ ios_t *ios_file(ios_t *s, char *fname, int rd, int wr, int create, int trunc);
|
|||
ios_t *ios_mem(ios_t *s, size_t initsize);
|
||||
ios_t *ios_str(ios_t *s, char *str);
|
||||
ios_t *ios_static_buffer(ios_t *s, char *buf, size_t sz);
|
||||
ios_t *ios_fd(ios_t *s, long fd, int isfile);
|
||||
ios_t *ios_fd(ios_t *s, long fd, int isfile, int own);
|
||||
// todo: ios_socket
|
||||
extern ios_t *ios_stdin;
|
||||
extern ios_t *ios_stdout;
|
||||
|
@ -119,6 +114,7 @@ int ios_ungetutf8(ios_t *s, uint32_t wc);
|
|||
int ios_getstringz(ios_t *dest, ios_t *src);
|
||||
int ios_getstringn(ios_t *dest, ios_t *src, size_t nchars);
|
||||
int ios_getline(ios_t *s, char **pbuf, size_t *psz);
|
||||
char *ios_readline(ios_t *s);
|
||||
|
||||
// discard data buffered for reading
|
||||
void ios_purge(ios_t *s);
|
||||
|
|
Loading…
Reference in New Issue