2 * Empire - A multi-player, client/server Internet based war game.
3 * Copyright (C) 1986-2009, Dave Pare, Jeff Bailey, Thomas Ruschak,
4 * Ken Stevens, Steve McClure
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 * See files README, COPYING and CREDITS in the root of the source
23 * tree for related information and legal notices. It is expected
24 * that future projects/authors will amend these files as needed.
28 * ringbuf.c: Simple ring buffer
30 * Known contributors to this file:
31 * Markus Armbruster, 2007-2009
43 * Initialize empty ring buffer.
44 * Not necessary if *R is already zeroed.
47 ring_init(struct ring *r)
49 r->cons = r->prod = 0;
53 * Return number of bytes held in ring buffer.
56 ring_len(struct ring *r)
58 assert(r->prod - r->cons <= RING_SIZE);
59 return r->prod - r->cons;
63 * Return how much space is left in ring buffer.
66 ring_space(struct ring *r)
68 return RING_SIZE - (r->prod - r->cons);
72 * Peek at ring buffer contents.
73 * N must be between -RING_SIZE-1 and RING_SIZE.
74 * If N>=0, peek at the (N+1)-th byte to be gotten.
75 * If N<0, peek at the -N-th byte that has been put in.
76 * Return the byte as unsigned char coverted to int, or EOF if there
77 * aren't that many bytes in the ring buffer.
80 ring_peek(struct ring *r, int n)
84 assert(-RING_SIZE - 1 <= n && n <= RING_SIZE);
86 idx = n >= 0 ? r->cons + n : r->prod - -n;
87 if (idx < r->cons && idx >= r->prod)
89 return r->buf[idx % RING_SIZE];
93 * Get and remove the oldest byte from the ring buffer.
94 * Return it as unsigned char coverted to int, or EOF if the buffer was
98 ring_getc(struct ring *r)
100 if (r->cons == r->prod)
102 return r->buf[r->cons++ % RING_SIZE];
106 * Attempt to put byte C into the ring buffer.
107 * Return EOF when the buffer is full, else C.
110 ring_putc(struct ring *r, unsigned char c)
112 if (r->prod - r->cons == RING_SIZE)
114 return r->buf[r->prod++ % RING_SIZE] = c;
118 * Attempt to put SZ bytes from BUF into the ring buffer.
119 * Return space left in ring buffer when it fits, else don't change
120 * the ring buffer and return how much space is missing times -1.
123 ring_putm(struct ring *r, void *buf, size_t sz)
126 int left = ring_space(r) - sz;
132 for (i = 0; i < sz; i++)
133 res = ring_putc(r, p[i]);
141 * Discard the N oldest bytes from the ring buffer.
142 * It must hold at least that many.
145 ring_discard(struct ring *r, int n)
147 assert(0 <= n && n <= ring_len(r));
152 * Search the ring buffer for zero-terminated string S.
153 * If found, return a non-negative value referring to the beginning of
154 * S in the buffer when passed to ring_peek(). Else return -1.
157 ring_search(struct ring *r, char *s)
159 size_t len = strlen(s);
162 for (i = r->cons; i + len <= r->prod; i++) {
163 for (j = 0; j < len && s[j] == r->buf[(i + j) % RING_SIZE]; j++) ;
171 * Fill ring buffer from file referred by file descriptor FD.
172 * If ring buffer is already full, do nothing and return 0.
173 * Else attempt to read as many bytes as space permits, with readv(),
174 * and return its value.
177 ring_from_file(struct ring *r, int fd)
179 unsigned cons = r->cons % RING_SIZE;
180 unsigned prod = r->prod % RING_SIZE;
185 if (r->prod == r->cons + RING_SIZE)
188 iov[0].iov_base = r->buf + prod;
191 iov[0].iov_len = RING_SIZE - prod;
192 /* r->buf[..cons-1] */
193 iov[1].iov_base = r->buf;
194 iov[1].iov_len = cons;
197 /* r->buf[prod..cons-1] */
198 iov[0].iov_len = cons - prod;
201 res = readv(fd, iov, cnt);
209 * Drain ring buffer to file referred by file descriptor FD.
210 * If ring buffer is already empty, do nothing and return 0.
211 * Else attempt to write complete contents with writev(), and return
215 ring_to_file(struct ring *r, int fd)
217 unsigned cons = r->cons % RING_SIZE;
218 unsigned prod = r->prod % RING_SIZE;
223 if (r->cons == r->prod)
226 iov[0].iov_base = r->buf + cons;
229 iov[0].iov_len = RING_SIZE - cons;
230 /* r->buf[..prod-1] */
231 iov[1].iov_base = r->buf;
232 iov[1].iov_len = prod;
235 /* r->buf[cons..prod-1] */
236 iov[0].iov_len = prod - cons;
239 res = writev(fd, iov, cnt);