]> git.pond.sub.org Git - empserver/blobdiff - src/client/ringbuf.c
Update copyright notice
[empserver] / src / client / ringbuf.c
index 95c9c0db14bed1274a98c75da2251f00eba6bd24..1a7aa04134faa35a580e670d1314827a39291b99 100644 (file)
@@ -1,11 +1,11 @@
 /*
  *  Empire - A multi-player, client/server Internet based war game.
- *  Copyright (C) 1986-2007, Dave Pare, Jeff Bailey, Thomas Ruschak,
- *                           Ken Stevens, Steve McClure
+ *  Copyright (C) 1986-2020, Dave Pare, Jeff Bailey, Thomas Ruschak,
+ *                Ken Stevens, Steve McClure, Markus Armbruster
  *
- *  This program is free software; you can redistribute it and/or modify
+ *  Empire 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
+ *  the Free Software Foundation, either version 3 of the License, or
  *  (at your option) any later version.
  *
  *  This program is distributed in the hope that it will be useful,
@@ -14,8 +14,7 @@
  *  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
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
  *
  *  ---
  *
@@ -26,9 +25,9 @@
  *  ---
  *
  *  ringbuf.c: Simple ring buffer
- * 
+ *
  *  Known contributors to this file:
- *     Markus Armbruster, 2007
+ *     Markus Armbruster, 2007-2017
  */
 
 #include <config.h>
 #include <assert.h>
 #include <stdio.h>
 #include <string.h>
-#ifndef _WIN32
-#include <sys/uio.h>
-#include <unistd.h>
-#else
-#define readv(fd, iov, iovcnt) \
-    w32_readv_handle((fd), (iov), (iovcnt))
-#define writev(fd, iov, iovcnt) \
-    w32_writev_socket((fd), (iov), (iovcnt))
-#endif
-#include "misc.h"
 #include "ringbuf.h"
 
 /*
  * Initialize empty ring buffer.
- * Not necessary if *R is already zeroed.
+ * Not necessary if *@r is already zeroed.
  */
 void
 ring_init(struct ring *r)
@@ -79,9 +68,9 @@ ring_space(struct ring *r)
 
 /*
  * Peek at ring buffer contents.
- * N must be between -RING_SIZE-1 and RING_SIZE.
- * If N>=0, peek at the (N+1)-th byte to be gotten.
- * If N<0, peek at the -N-th byte that has been put in.
+ * @n must be between -RING_SIZE-1 and RING_SIZE.
+ * If @n>=0, peek at the (@n+1)-th byte to be gotten.
+ * If @n<0, peek at the -@n-th byte that has been put in.
  * Return the byte as unsigned char coverted to int, or EOF if there
  * aren't that many bytes in the ring buffer.
  */
@@ -92,15 +81,23 @@ ring_peek(struct ring *r, int n)
 
     assert(-RING_SIZE - 1 <= n && n <= RING_SIZE);
 
-    idx = n >= 0 ? r->cons + n : r->prod - -n;
-    if (idx < r->cons && idx >= r->prod)
-       return EOF;
+    if (n >= 0) {
+       idx = r->cons + n;
+       if (idx >= r->prod)
+           return EOF;
+    } else {
+       /* Beware, r->prod - -n can wrap around, avoid that */
+       if (r->prod < r->cons + -n)
+           return EOF;
+       idx = r->prod - -n;
+    }
+
     return r->buf[idx % RING_SIZE];
 }
 
 /*
  * Get and remove the oldest byte from the ring buffer.
- * Return it as unsigned char coverted to int, or EOF if the buffer was
+ * Return it as unsigned char converted to int, or EOF if the buffer was
  * empty.
  */
 int
@@ -112,8 +109,8 @@ ring_getc(struct ring *r)
 }
 
 /*
- * Attempt to put byte C into the ring buffer.
- * Return EOF when the buffer is full, else C.
+ * Attempt to put byte @c into the ring buffer.
+ * Return EOF when the buffer is full, else @c.
  */
 int
 ring_putc(struct ring *r, unsigned char c)
@@ -124,7 +121,7 @@ ring_putc(struct ring *r, unsigned char c)
 }
 
 /*
- * Attempt to put SZ bytes from BUF into the ring buffer.
+ * Attempt to put @sz bytes from @buf into the ring buffer.
  * Return space left in ring buffer when it fits, else don't change
  * the ring buffer and return how much space is missing times -1.
  */
@@ -147,7 +144,7 @@ ring_putm(struct ring *r, void *buf, size_t sz)
 }
 
 /*
- * Discard the N oldest bytes from the ring buffer.
+ * Discard the @n oldest bytes from the ring buffer.
  * It must hold at least that many.
  */
 void
@@ -158,18 +155,20 @@ ring_discard(struct ring *r, int n)
 }
 
 /*
- * Search the ring buffer for zero-terminated string S.
- * If found, return a non-negative value referring to the beginning of
- * S in the buffer when passed to ring_peek().  Else return -1.
+ * Search the ring buffer for zero-terminated string @s.
+ * Start at the (@n+1)-th byte to be gotten.
+ * If found, return the number of bytes in the buffer before @s.
+ * Else return -1.
  */
 int
-ring_search(struct ring *r, char *s)
+ring_search(struct ring *r, char *s, int n)
 {
     size_t len = strlen(s);
     size_t i, j;
 
-    for (i = r->cons; i + len <= r->prod; i++) {
-       for (j = 0; j < len && s[j] == r->buf[(i + j) % RING_SIZE]; j++) ;
+    for (i = r->cons + n; i + len <= r->prod; i++) {
+       for (j = 0; s[j] && s[j] == (char)r->buf[(i + j) % RING_SIZE]; j++)
+           ;
        if (!s[j])
            return i - r->cons;
     }
@@ -177,7 +176,7 @@ ring_search(struct ring *r, char *s)
 }
 
 /*
- * Fill ring buffer from file referred by file descriptor FD.
+ * Fill ring buffer from file referred by file descriptor @fd.
  * If ring buffer is already full, do nothing and return 0.
  * Else attempt to read as many bytes as space permits, with readv(),
  * and return its value.
@@ -215,39 +214,29 @@ ring_from_file(struct ring *r, int fd)
 }
 
 /*
- * Drain ring buffer to file referred by file descriptor FD.
- * If ring buffer is already empty, do nothing and return 0.
- * Else attempt to write complete contents with writev(), and return
- * its value.
+ * Set up @iov[] to describe complete contents of ring buffer.
+ * @iov[] must have at least two elements.
+ * Return number of elements used (zero for an empty ring buffer).
  */
 int
-ring_to_file(struct ring *r, int fd)
+ring_to_iovec(struct ring *r, struct iovec iov[])
 {
     unsigned cons = r->cons % RING_SIZE;
     unsigned prod = r->prod % RING_SIZE;
-    struct iovec iov[2];
-    int cnt;
-    ssize_t res;
 
     if (r->cons == r->prod)
        return 0;
 
     iov[0].iov_base = r->buf + cons;
-    if (prod <= cons) {
-       /* r->buf[cons..] */
-       iov[0].iov_len = RING_SIZE - cons;
-       /* r->buf[..prod-1] */
-       iov[1].iov_base = r->buf;
-       iov[1].iov_len = prod;
-       cnt = 2;
-    } else {
+    if (prod > cons) {
        /* r->buf[cons..prod-1] */
        iov[0].iov_len = prod - cons;
-       cnt = 1;
+       return 1;
     }
-    res = writev(fd, iov, cnt);
-    if (res < 0)
-       return res;
-    r->cons += res;
-    return res;
+    /* r->buf[cons..] */
+    iov[0].iov_len = RING_SIZE - cons;
+    /* r->buf[..prod-1] */
+    iov[1].iov_base = r->buf;
+    iov[1].iov_len = prod;
+    return 2;
 }