From af64cfd4917bc510cd8ab10e7c4c561189d149f7 Mon Sep 17 00:00:00 2001 From: Ron Koenderink Date: Thu, 16 Aug 2007 21:43:20 +0000 Subject: [PATCH] [_WIN32] (readv, writev, iovec): New. POSIX equivalents. (ioq_makeiov, ioqtoiov): Compile unconditionally. (io_output): Use POSIX code unconditionally. [_WIN32] (ioq_makebuf): Remove. --- include/ioqueue.h | 4 --- src/lib/gen/io.c | 15 +------- src/lib/gen/ioqueue.c | 52 --------------------------- src/lib/w32/posixio.c | 83 +++++++++++++++++++++++++++++++++++++++++++ src/lib/w32/sys/uio.h | 51 ++++++++++++++++++++++++++ 5 files changed, 135 insertions(+), 70 deletions(-) create mode 100644 src/lib/w32/sys/uio.h diff --git a/include/ioqueue.h b/include/ioqueue.h index 0049be20..8aaf1561 100644 --- a/include/ioqueue.h +++ b/include/ioqueue.h @@ -56,11 +56,7 @@ struct ioqueue { extern struct ioqueue *ioq_create(int size); extern void ioq_destroy(struct ioqueue *ioq); extern void ioq_drain(struct ioqueue *ioq); -#if defined (_WIN32) -extern int ioq_makebuf(struct ioqueue *ioq, char *pBuf, int nBufLen); -#else extern int ioq_makeiov(struct ioqueue *ioq, struct iovec *iov, int cc); -#endif extern int ioq_peek(struct ioqueue *ioq, char *buf, int cc); extern int ioq_dequeue(struct ioqueue *ioq, int cc); extern void ioq_append(struct ioqueue *ioq, char *buf, int cc); diff --git a/src/lib/gen/io.c b/src/lib/gen/io.c index 61c21d91..ab2bebda 100644 --- a/src/lib/gen/io.c +++ b/src/lib/gen/io.c @@ -45,8 +45,8 @@ #include #include #include -#if !defined(_WIN32) #include +#if !defined(_WIN32) #include #endif #include @@ -166,11 +166,7 @@ io_outputwaiting(struct iop *iop) int io_output(struct iop *iop, int waitforoutput) { -#if !defined(_WIN32) struct iovec iov[16]; -#else - char buf[IO_BUFSIZE]; -#endif int cc; int n; int remain; @@ -187,15 +183,10 @@ io_output(struct iop *iop, int waitforoutput) if (iop->flags & IO_ERROR) return -1; -#if !defined(_WIN32) /* make the iov point to the data in the queue. */ /* I.E., each of the elements in the queue. */ /* returns the number of elements in the iov. */ n = ioq_makeiov(iop->output, iov, IO_BUFSIZE); -#else - /* Make a buffer containing the output to write. */ - n = ioq_makebuf(iop->output, buf, sizeof(buf)); -#endif if (n <= 0) { return 0; @@ -209,11 +200,7 @@ io_output(struct iop *iop, int waitforoutput) } /* Do the actual write. */ -#if !defined(_WIN32) cc = writev(iop->fd, iov, n); -#else - cc = write(iop->fd, buf, n); -#endif /* if it failed.... */ if (cc < 0) { diff --git a/src/lib/gen/ioqueue.c b/src/lib/gen/ioqueue.c index 18cf1b5b..926c0f55 100644 --- a/src/lib/gen/ioqueue.c +++ b/src/lib/gen/ioqueue.c @@ -42,17 +42,13 @@ #include #include #include -#if !defined(_WIN32) #include -#endif #include "ioqueue.h" #include "misc.h" #include "queue.h" static int ioqtocbuf(struct ioqueue *ioq, char *buf, int cc, int stopc); -#if !defined(_WIN32) static int ioqtoiov(struct ioqueue *ioq, struct iovec *iov, int max); -#endif static int ioqtobuf(struct ioqueue *ioq, char *buf, int cc); static int appendcc(struct ioqueue *ioq, char *buf, int cc); static int removecc(struct ioqueue *ioq, int cc); @@ -101,7 +97,6 @@ ioq_drain(struct ioqueue *ioq) * iovec, but don't actually dequeue the data. * return # of iovec initialized. */ -#if !defined(_WIN32) int ioq_makeiov(struct ioqueue *ioq, struct iovec *iov, int cc) { @@ -109,7 +104,6 @@ ioq_makeiov(struct ioqueue *ioq, struct iovec *iov, int cc) return 0; return ioqtoiov(ioq, iov, cc); } -#endif /* * Copy the specified number of characters into the buffer @@ -247,7 +241,6 @@ ioqtocbuf(struct ioqueue *ioq, char *buf, int cc, int stopc) * initialize an iovec to point at max bytes worth * of data from the ioqueue. */ -#if !defined(_WIN32) static int ioqtoiov(struct ioqueue *ioq, struct iovec *iov, int max) { @@ -274,7 +267,6 @@ ioqtoiov(struct ioqueue *ioq, struct iovec *iov, int max) } return niov; } -#endif /* * append a buffer to the end of the ioq. @@ -356,47 +348,3 @@ removecc(struct ioqueue *ioq, int cc) ioq->cc -= nbytes; return nbytes; } - -#if defined(_WIN32) -/* - * Make an (output) buffer up to the - * maximum size of the buffer. - * - * We don't free the bytes... - */ -int -ioq_makebuf(struct ioqueue *ioq, char *pBuf, int nBufLen) -{ - struct io *io; - struct emp_qelem *qp; - struct emp_qelem *head; - int nbytes; - int nleft; - int ncopied; - char *offset; - - ncopied = 0; - nleft = nBufLen; - offset = pBuf; - head = &ioq->list.queue; - - for (qp = head->q_forw; (qp != head) && (nleft > 0); qp = qp->q_forw) { - io = (struct io *)qp; - nbytes = io->nbytes - io->offset; - if (nbytes < 0) { - /* Paranoid check for bad buffer. */ - continue; - } - - /* too many bytes, wait till next time. */ - if (nbytes > nleft) - break; - - memcpy(offset, io->data + io->offset, nbytes); - offset += nbytes; - nleft -= nbytes; - ncopied += nbytes; - } - return ncopied; -} -#endif /* _WIN32 */ diff --git a/src/lib/w32/posixio.c b/src/lib/w32/posixio.c index d7e88b63..b031ee28 100644 --- a/src/lib/w32/posixio.c +++ b/src/lib/w32/posixio.c @@ -54,6 +54,7 @@ #include #include "unistd.h" +#include "sys/uio.h" #include "empio.h" #include "prototypes.h" @@ -445,6 +446,51 @@ posix_read(int fd, void *buffer, unsigned int count) _read(handle, buffer, count)) } +/* + * POSIX equivalent for readv + * Modelled after the GNU's libc/sysdeps/posix/readv.c + */ +ssize_t +readv(int fd, const struct iovec *iov, int iovcnt) +{ + int i; + unsigned char *buffer, *buffer_location; + size_t total_bytes = 0; + int bytes_read; + size_t bytes_left; + + for (i = 0; i < iovcnt; i++) { + total_bytes += iov[i].iov_len; + } + + buffer = malloc(total_bytes); + if (buffer == NULL) + return -1; + + bytes_read = posix_read(fd, buffer, total_bytes); + if (bytes_read <= 0) { + free(buffer); + return -1; + } + + bytes_left = bytes_read; + buffer_location = buffer; + for (i = 0; i < iovcnt; i++) { + size_t copy = MIN(iov[i].iov_len, bytes_left); + + memcpy(iov[i].iov_base, buffer_location, copy); + + buffer_location += copy; + bytes_left -= copy; + if (bytes_left == 0) + break; + } + + free(buffer); + + return bytes_read; +} + /* * POSIX equivalent for write(). */ @@ -455,6 +501,43 @@ posix_write(int fd, const void *buffer, unsigned int count) _write(handle, buffer, count)) } +/* + * POSIX equivalent for writev + * Modelled after the GNU's libc/sysdeps/posix/writev.c + */ +ssize_t +writev(int fd, const struct iovec *iov, int iovcnt) +{ + int i; + unsigned char *buffer, *buffer_location; + size_t total_bytes = 0; + int bytes_written; + + for (i = 0; i < iovcnt; i++) + total_bytes += iov[i].iov_len; + + if (total_bytes == 0) + return 0; + + buffer = malloc(total_bytes); + if (buffer == NULL) + return -1; + + buffer_location = buffer; + for (i = 0; i < iovcnt; i++) { + memcpy(buffer_location, iov[i].iov_base, iov[i].iov_len); + buffer_location += iov[i].iov_len; + } + + bytes_written = posix_write(fd, buffer, total_bytes); + + free(buffer); + + if (bytes_written <= 0) + return -1; + return bytes_written; +} + /* * POSIX equivalent for fileno(). * As fopen/fclose/fcloseall are not implemented as POSIX diff --git a/src/lib/w32/sys/uio.h b/src/lib/w32/sys/uio.h new file mode 100644 index 00000000..043e62b3 --- /dev/null +++ b/src/lib/w32/sys/uio.h @@ -0,0 +1,51 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2007, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See files README, COPYING and CREDITS in the root of the source + * tree for related information and legal notices. It is expected + * that future projects/authors will amend these files as needed. + * + * --- + * + * sys/socket.h: POSIX io vector emulation for WIN32 + * + * Known contributors to this file: + * Ron Koenderink, 2007 + */ + +#ifndef SYS_UIO_H +#define SYS_UIO_H + +#include +#include "w32misc.h" + +struct iovec { + /*Base address of a memory region for input or output. */ + void *iov_base; + + /* The size of the memory pointed to by iov_base. */ + size_t iov_len; +}; + +extern ssize_t readv(int fd, const struct iovec *iov, int iovcnt); +extern ssize_t writev(int fd, const struct iovec *iov, int iovcnt); + +#endif /* SYS_UIO_H */