]> git.pond.sub.org Git - empserver/blob - src/client/ioqueue.c
(iovec, ioq_peekiov, ioqtoiov): Unused, minor portability
[empserver] / src / client / ioqueue.c
1 /*
2  *  Empire - A multi-player, client/server Internet based war game.
3  *  Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak,
4  *                           Ken Stevens, Steve McClure
5  *
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.
10  *
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.
15  *
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
19  *
20  *  ---
21  *
22  *  See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the
23  *  related information and legal notices. It is expected that any future
24  *  projects/authors will amend these files as needed.
25  *
26  *  ---
27  *
28  *  ioqueue.c: Manage an i/o queue
29  * 
30  *  Known contributors to this file:
31  *     Steve McClure, 1998
32  */
33
34 #include <stdio.h>
35 #include <stdlib.h>
36 #include <string.h>
37 #include <sys/types.h>
38 #include "misc.h"
39 #include "queue.h"
40 #include "ioqueue.h"
41
42 static int ioqtobuf(register struct ioqueue *ioq, s_char *buf, int cc);
43 static void enqueuecc(struct ioqueue *ioq, s_char *buf, int cc);
44 static int dequeuecc(register struct ioqueue *ioq, register int cc);
45
46 void insque(struct qelem *, struct qelem *);
47 void remque(struct qelem *);
48 void initque(struct qelem *p);
49 struct qelem *makeqt(int nelem);
50
51 void
52 ioq_init(struct ioqueue *ioq, int bsize)
53 {
54     extern s_char num_teles[];
55
56     initque(&ioq->queue);
57     ioq->cc = 0;
58     ioq->bsize = bsize;
59     *num_teles = '\0';
60 }
61
62 /*
63  * Copy the specified number of characters into the buffer
64  * provided, without actually dequeueing the data.  Return
65  * number of bytes actually found.
66  */
67 int
68 ioq_peek(struct ioqueue *ioq, s_char *buf, int cc)
69 {
70     return ioqtobuf(ioq, buf, cc);
71 }
72
73 int
74 ioq_dequeue(struct ioqueue *ioq, int cc)
75 {
76     if (dequeuecc(ioq, cc) != cc)
77         return 0;
78     return cc;
79 }
80
81 int
82 ioq_read(struct ioqueue *ioq, s_char *buf, int cc)
83 {
84     int n;
85
86     n = ioqtobuf(ioq, buf, cc);
87     if (n > 0)
88         dequeuecc(ioq, n);
89     return n;
90 }
91
92 void
93 ioq_write(struct ioqueue *ioq, s_char *buf, int cc)
94 {
95     enqueuecc(ioq, buf, cc);
96 }
97
98 int
99 ioq_qsize(struct ioqueue *ioq)
100 {
101     return ioq->cc;
102 }
103
104 void
105 ioq_drain(struct ioqueue *ioq)
106 {
107     struct io *io;
108     struct qelem *qp;
109
110     while ((qp = ioq->queue.q_forw) != &ioq->queue) {
111         io = (struct io *)qp;
112         free(io->data);
113         (void)remque(&io->queue);
114         (void)free(io);
115     }
116     ioq->cc = 0;
117 }
118
119 s_char *
120 ioq_gets(struct ioqueue *ioq, s_char *buf, int cc)
121 {
122     register s_char *p;
123     register s_char *end;
124     int nbytes;
125
126     nbytes = ioqtobuf(ioq, buf, cc);
127     if (nbytes < cc)
128         cc = nbytes;
129     end = &buf[cc];
130     for (p = buf; p < end && *p; p++) {
131         if (*p == '\n') {
132             *p = '\0';
133             dequeuecc(ioq, (p - buf) + 1);
134             return buf;
135         }
136     }
137     return 0;
138 }
139
140 /*
141  * all the rest are local to this module
142  */
143
144
145 /*
146  * copy cc bytes from ioq to buf.
147  * this routine doesn't free memory; this is
148  * left for a higher level.
149  */
150 static int
151 ioqtobuf(register struct ioqueue *ioq, s_char *buf, int cc)
152 {
153     register struct io *io;
154     struct qelem *qp;
155     s_char *offset;
156     int nbytes;
157     int nleft;
158
159     nleft = cc;
160     offset = buf;
161     for (qp = ioq->queue.q_forw; qp != &ioq->queue; qp = qp->q_forw) {
162         io = (struct io *)qp;
163         if ((nbytes = io->nbytes - io->offset) < 0) {
164             fprintf(stderr, "ioqtobuf: offset %d nbytes %d\n",
165                     io->offset, io->nbytes);
166             continue;
167         }
168         if (nbytes > 0) {
169             if (nleft < nbytes)
170                 nbytes = nleft;
171             memcpy(offset, io->data + io->offset, nbytes);
172             offset += nbytes;
173             nleft -= nbytes;
174         }
175     }
176     return offset - buf;
177 }
178
179 /*
180  * append a buffer to the end of the ioq.
181  */
182 static void
183 enqueuecc(struct ioqueue *ioq, s_char *buf, int cc)
184 {
185     struct io *io;
186
187     io = (struct io *)malloc(sizeof(*io));
188     io->nbytes = cc;
189     io->offset = 0;
190     io->data = buf;
191     insque(&io->queue, ioq->queue.q_back);
192     ioq->cc += cc;
193 }
194
195 /*
196  * remove cc bytes from ioqueue ioq
197  * free memory, dequeue io elements
198  * which are no longer used.
199  */
200 static int
201 dequeuecc(register struct ioqueue *ioq, register int cc)
202 {
203     register struct io *io;
204     register struct qelem *qp;
205     register int nbytes;
206     register int there;
207
208     nbytes = 0;
209     while ((qp = ioq->queue.q_forw) != &ioq->queue) {
210         io = (struct io *)qp;
211         there = io->nbytes - io->offset;
212         if (there < 0) {
213             fprintf(stderr, "dequeuecc: nbytes %d, offset %d\n",
214                     io->nbytes, io->offset);
215             continue;
216         }
217         if (cc > there) {
218             cc -= there;
219             nbytes += there;
220             (void)remque(&io->queue);
221             free(io->data);
222         } else {
223             io->offset += cc;
224             nbytes += cc;
225             break;
226         }
227     }
228     ioq->cc -= nbytes;
229     return nbytes;
230 }