lib: Introduced a portable abstraction layer for custom stdio streams.
authorFredrik Tolf <fredrik@dolda2000.com>
Sun, 2 Mar 2014 09:17:48 +0000 (10:17 +0100)
committerFredrik Tolf <fredrik@dolda2000.com>
Sun, 2 Mar 2014 09:17:48 +0000 (10:17 +0100)
lib/mtio.c
lib/utils.c
lib/utils.h

index 70a0949..1f4a579 100644 (file)
@@ -38,7 +38,7 @@ struct stdiofd {
     int timeout;
 };
 
-static ssize_t mtread(void *cookie, char *buf, size_t len)
+static ssize_t mtread(void *cookie, void *buf, size_t len)
 {
     struct stdiofd *d = cookie;
     int ev;
@@ -63,7 +63,7 @@ static ssize_t mtread(void *cookie, char *buf, size_t len)
     }
 }
 
-static ssize_t mtwrite(void *cookie, const char *buf, size_t len)
+static ssize_t mtwrite(void *cookie, const void *buf, size_t len)
 {
     struct stdiofd *d = cookie;
     int ev;
@@ -107,40 +107,6 @@ static int mtclose(void *cookie)
     return(0);
 }
 
-#if defined(HAVE_GLIBC_STDIO)
-static cookie_io_functions_t iofuns = {
-    .read = mtread,
-    .write = mtwrite,
-    .close = mtclose,
-};
-
-FILE *mtstdopen(int fd, int issock, int timeout, char *mode)
-{
-    struct stdiofd *d;
-    FILE *ret;
-    
-    omalloc(d);
-    d->fd = fd;
-    d->sock = issock;
-    d->timeout = timeout;
-    ret = fopencookie(d, mode, iofuns);
-    if(!ret)
-       free(d);
-    else
-       fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) | O_NONBLOCK);
-    return(ret);
-}
-#elif defined(HAVE_BSD_STDIO)
-static int bsd2mtread(void *cookie, char *buf, int len)
-{
-    return(mtread(cookie, buf, len));
-}
-
-static int bsd2mtwrite(void *cookie, const char *buf, int len)
-{
-    return(mtwrite(cookie, buf, len));
-}
-
 FILE *mtstdopen(int fd, int issock, int timeout, char *mode)
 {
     struct stdiofd *d;
@@ -160,13 +126,10 @@ FILE *mtstdopen(int fd, int issock, int timeout, char *mode)
     d->fd = fd;
     d->sock = issock;
     d->timeout = timeout;
-    ret = funopen(d, r?bsd2mtread:NULL, w?bsd2mtwrite:NULL, NULL, mtclose);
+    ret = funstdio(d, r?mtread:NULL, w?mtwrite:NULL, NULL, mtclose);
     if(!ret)
        free(d);
     else
        fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) | O_NONBLOCK);
     return(ret);
 }
-#else
-#error "No stdio implementation for this system"
-#endif
index 459afed..ed22b42 100644 (file)
     along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
 
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
 #include <stdlib.h>
 #include <stdio.h>
 #include <string.h>
 #include <ctype.h>
+#include <errno.h>
 
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
 #include <utils.h>
 
 static char *base64set = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
@@ -474,3 +475,127 @@ void *btreeget(struct btree *tree, void *key, int (*cmp)(void *, void *))
            return(tree->d);
     }
 }
+
+struct stdif {
+    ssize_t (*read)(void *pdata, void *buf, size_t len);
+    ssize_t (*write)(void *pdata, const void *buf, size_t len);
+    off_t (*seek)(void *pdata, off_t offset, int whence);
+    int (*close)(void *pdata);
+    void *pdata;
+};
+
+#if defined(HAVE_GLIBC_STDIO)
+static ssize_t wrapread(void *pdata, char *buf, size_t len)
+{
+    struct stdif *nf = pdata;
+    
+    return(nf->read(nf->pdata, buf, len));
+}
+
+static ssize_t wrapwrite(void *pdata, const char *buf, size_t len)
+{
+    struct stdif *nf = pdata;
+    
+    return(nf->write(nf->pdata, buf, len));
+}
+
+static int wrapseek(void *pdata, off_t *pos, int whence)
+{
+    struct stdif *nf = pdata;
+    off_t ret;
+    
+    ret = nf->seek(nf->pdata, *pos, whence);
+    if(ret < 0)
+       return(-1);
+    *pos = ret;
+    return(0);
+}
+
+static int wrapclose(void *pdata)
+{
+    struct stdif *nf = pdata;
+    int ret;
+    
+    if(nf->close != NULL)
+       ret = nf->close(nf->pdata);
+    free(nf);
+    return(ret);
+}
+
+FILE *funstdio(void *pdata,
+              ssize_t (*read)(void *pdata, void *buf, size_t len),
+              ssize_t (*write)(void *pdata, const void *buf, size_t len),
+              off_t (*seek)(void *pdata, off_t offset, int whence),
+              int (*close)(void *pdata))
+{
+    struct stdif *nf;
+    cookie_io_functions_t io;
+    char *mode;
+    
+    if(read && write) {
+       mode = "r+";
+    } else if(read) {
+       mode = "r";
+    } else if(write) {
+       mode = "w";
+    } else {
+       errno = EINVAL;
+       return(NULL);
+    }
+    omalloc(nf);
+    *nf = (struct stdif){.read = read, .write = write, .seek = seek, .close = close, .pdata = pdata};
+    io = (cookie_io_functions_t) {
+       .read = read?wrapread:NULL,
+       .write = write?wrapwrite:NULL,
+       .seek = seek?wrapseek:NULL,
+       .close = wrapclose,
+    };
+    return(fopencookie(nf, mode, io));
+}
+#elif defined(HAVE_BSD_STDIO)
+static int wrapread(void *pdata, char *buf, int len)
+{
+    struct stdif *nf = pdata;
+    
+    return(nf->read(nf->pdata, buf, len));
+}
+
+static int wrapwrite(void *pdata, const char *buf, int len)
+{
+    struct stdif *nf = pdata;
+    
+    return(nf->write(nf->pdata, buf, len));
+}
+
+static fpos_t wrapseek(void *pdata, fpos_t pos, int whence)
+{
+    struct stdif *nf = pdata;
+    
+    return(nf->seek(nf->pdata, pos, whence));
+}
+
+static int wrapclose(void *pdata)
+{
+    struct stdif *nf = pdata;
+    int ret;
+    
+    if(nf->close != NULL)
+       ret = nf->close(nf->pdata);
+    free(nf);
+    return(ret);
+}
+
+FILE *funstdio(void *pdata,
+              ssize_t (*read)(void *pdata, void *buf, size_t len),
+              ssize_t (*write)(void *pdata, const void *buf, size_t len),
+              off_t (*seek)(void *pdata, off_t offset, int whence),
+              int (*close)(void *pdata))
+{
+    struct stdif *nf;
+    
+    omalloc(nf);
+    return(funopen(pdata, read?wrapread:NULL, write:wrapwrite:NULL, seek:wrapseek:NULL, wrapclose));
+}
+#else
+#error "No stdio implementation for this system"
+#endif
index 080864b..4fdde3c 100644 (file)
@@ -1,6 +1,7 @@
 #ifndef _UTILS_H
 #define _UTILS_H
 
+#include <stdio.h>
 #include <stdarg.h>
 #include <sys/types.h>
 
@@ -86,5 +87,10 @@ int bbtreedel(struct btree **tree, void *item, int (*cmp)(void *, void *));
 void freebtree(struct btree **tree, void (*ffunc)(void *));
 int bbtreeput(struct btree **tree, void *item, int (*cmp)(void *, void *));
 void *btreeget(struct btree *tree, void *key, int (*cmp)(void *, void *));
+FILE *funstdio(void *pdata,
+              ssize_t (*read)(void *pdata, void *buf, size_t len),
+              ssize_t (*write)(void *pdata, const void *buf, size_t len),
+              off_t (*seek)(void *pdata, off_t offset, int whence),
+              int (*close)(void *pdata));
 
 #endif