shithub: femtolisp

Download patch

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);