ref: 21dd64045484411ef9c9f218c1490fd02c02b3fd
parent: 3d25a1a67201e5bf9767206908391f0b0484457c
author: JeffBezanson <jeff.bezanson@gmail.com>
date: Mon Jan 16 23:31:08 EST 2012
some fixes to ios
--- a/llt/ios.c
+++ b/llt/ios.c
@@ -45,20 +45,6 @@
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 @@
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 @@
buf += wrote;
if (err)
return err;
- if (wrote == 0)
- _fd_poll(fd, 1);
}
return 0;
}
@@ -274,6 +256,7 @@
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 @@
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 @@
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 @@
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,9 +396,14 @@
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;
}
@@ -426,15 +410,53 @@
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 @@
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,32 +509,8 @@
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)
{
if (s->ndirty == 0 || s->bm == bm_mem || s->buf == NULL)
@@ -522,6 +524,7 @@
}
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 @@
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 @@
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,10 +689,14 @@
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) {
@@ -696,6 +703,7 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
if (ios_read(s, &ch, 1) < 1)
return IOS_EOF;
}
+ if (ch == '\n') s->lineno++;
return (unsigned char)ch;
}
@@ -935,6 +945,15 @@
}
}
+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)
@@ -941,6 +960,8 @@
{
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;
@@ -947,6 +968,7 @@
char *start = s->buf + s->bpos;
c = vsnprintf(start, avail, format, args);
if (c < 0) {
+ va_end(al);
return c;
}
if (c < avail) {
@@ -955,10 +977,11 @@
// 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);
@@ -965,6 +988,7 @@
LLT_FREE(str);
}
+ va_end(al);
return c;
}
--- a/llt/ios.h
+++ b/llt/ios.h
@@ -11,7 +11,7 @@
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 @@
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 @@
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_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_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);