Annotation of src/usr.bin/telnet/ring.c, Revision 1.2
1.2 ! niklas 1: /* $OpenBSD$ */
! 2: /* $NetBSD: ring.c,v 1.7 1996/02/28 21:04:07 thorpej Exp $ */
! 3:
1.1 deraadt 4: /*
5: * Copyright (c) 1988, 1993
6: * The Regents of the University of California. All rights reserved.
7: *
8: * Redistribution and use in source and binary forms, with or without
9: * modification, are permitted provided that the following conditions
10: * are met:
11: * 1. Redistributions of source code must retain the above copyright
12: * notice, this list of conditions and the following disclaimer.
13: * 2. Redistributions in binary form must reproduce the above copyright
14: * notice, this list of conditions and the following disclaimer in the
15: * documentation and/or other materials provided with the distribution.
16: * 3. All advertising materials mentioning features or use of this software
17: * must display the following acknowledgement:
18: * This product includes software developed by the University of
19: * California, Berkeley and its contributors.
20: * 4. Neither the name of the University nor the names of its contributors
21: * may be used to endorse or promote products derived from this software
22: * without specific prior written permission.
23: *
24: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34: * SUCH DAMAGE.
35: */
36:
37: #ifndef lint
1.2 ! niklas 38: #if 0
! 39: static char sccsid[] = "@(#)ring.c 8.2 (Berkeley) 5/30/95";
! 40: static char rcsid[] = "$NetBSD: ring.c,v 1.7 1996/02/28 21:04:07 thorpej Exp $";
! 41: #else
! 42: static char rcsid[] = "$OpenBSD$";
! 43: #endif
1.1 deraadt 44: #endif /* not lint */
45:
46: /*
47: * This defines a structure for a ring buffer.
48: *
49: * The circular buffer has two parts:
50: *(((
51: * full: [consume, supply)
52: * empty: [supply, consume)
53: *]]]
54: *
55: */
56:
57: #include <stdio.h>
58: #ifndef NO_STRING_H
59: #include <string.h>
60: #endif
61: #include <strings.h>
62: #include <errno.h>
63:
64: #ifdef size_t
65: #undef size_t
66: #endif
67:
68: #include <sys/types.h>
69: #ifndef FILIO_H
70: #include <sys/ioctl.h>
71: #endif
72: #include <sys/socket.h>
73:
74: #include "ring.h"
75: #include "general.h"
76:
77: /* Internal macros */
78:
79: #if !defined(MIN)
80: #define MIN(a,b) (((a)<(b))? (a):(b))
81: #endif /* !defined(MIN) */
82:
83: #define ring_subtract(d,a,b) (((a)-(b) >= 0)? \
84: (a)-(b): (((a)-(b))+(d)->size))
85:
86: #define ring_increment(d,a,c) (((a)+(c) < (d)->top)? \
87: (a)+(c) : (((a)+(c))-(d)->size))
88:
89: #define ring_decrement(d,a,c) (((a)-(c) >= (d)->bottom)? \
90: (a)-(c) : (((a)-(c))-(d)->size))
91:
92:
93: /*
94: * The following is a clock, used to determine full, empty, etc.
95: *
96: * There is some trickiness here. Since the ring buffers are initialized
97: * to ZERO on allocation, we need to make sure, when interpreting the
98: * clock, that when the times are EQUAL, then the buffer is FULL.
99: */
100: static u_long ring_clock = 0;
101:
102:
103: #define ring_empty(d) (((d)->consume == (d)->supply) && \
104: ((d)->consumetime >= (d)->supplytime))
105: #define ring_full(d) (((d)->supply == (d)->consume) && \
106: ((d)->supplytime > (d)->consumetime))
107:
108:
109:
110:
111:
112: /* Buffer state transition routines */
113:
114: ring_init(ring, buffer, count)
115: Ring *ring;
116: unsigned char *buffer;
117: int count;
118: {
119: memset((char *)ring, 0, sizeof *ring);
120:
121: ring->size = count;
122:
123: ring->supply = ring->consume = ring->bottom = buffer;
124:
125: ring->top = ring->bottom+ring->size;
126:
127:
128: return 1;
129: }
130:
131: /* Mark routines */
132:
133: /*
134: * Mark the most recently supplied byte.
135: */
136:
137: void
138: ring_mark(ring)
139: Ring *ring;
140: {
141: ring->mark = ring_decrement(ring, ring->supply, 1);
142: }
143:
144: /*
145: * Is the ring pointing to the mark?
146: */
147:
148: int
149: ring_at_mark(ring)
150: Ring *ring;
151: {
152: if (ring->mark == ring->consume) {
153: return 1;
154: } else {
155: return 0;
156: }
157: }
158:
159: /*
160: * Clear any mark set on the ring.
161: */
162:
163: void
164: ring_clear_mark(ring)
165: Ring *ring;
166: {
167: ring->mark = 0;
168: }
169:
170: /*
171: * Add characters from current segment to ring buffer.
172: */
173: void
174: ring_supplied(ring, count)
175: Ring *ring;
176: int count;
177: {
178: ring->supply = ring_increment(ring, ring->supply, count);
179: ring->supplytime = ++ring_clock;
180: }
181:
182: /*
183: * We have just consumed "c" bytes.
184: */
185: void
186: ring_consumed(ring, count)
187: Ring *ring;
188: int count;
189: {
190: if (count == 0) /* don't update anything */
191: return;
192:
193: if (ring->mark &&
194: (ring_subtract(ring, ring->mark, ring->consume) < count)) {
195: ring->mark = 0;
196: }
197: ring->consume = ring_increment(ring, ring->consume, count);
198: ring->consumetime = ++ring_clock;
199: /*
200: * Try to encourage "ring_empty_consecutive()" to be large.
201: */
202: if (ring_empty(ring)) {
203: ring->consume = ring->supply = ring->bottom;
204: }
205: }
206:
207:
208:
209: /* Buffer state query routines */
210:
211:
212: /* Number of bytes that may be supplied */
213: int
214: ring_empty_count(ring)
215: Ring *ring;
216: {
217: if (ring_empty(ring)) { /* if empty */
218: return ring->size;
219: } else {
220: return ring_subtract(ring, ring->consume, ring->supply);
221: }
222: }
223:
224: /* number of CONSECUTIVE bytes that may be supplied */
225: int
226: ring_empty_consecutive(ring)
227: Ring *ring;
228: {
229: if ((ring->consume < ring->supply) || ring_empty(ring)) {
230: /*
231: * if consume is "below" supply, or empty, then
232: * return distance to the top
233: */
234: return ring_subtract(ring, ring->top, ring->supply);
235: } else {
236: /*
237: * else, return what we may.
238: */
239: return ring_subtract(ring, ring->consume, ring->supply);
240: }
241: }
242:
243: /* Return the number of bytes that are available for consuming
244: * (but don't give more than enough to get to cross over set mark)
245: */
246:
247: int
248: ring_full_count(ring)
249: Ring *ring;
250: {
251: if ((ring->mark == 0) || (ring->mark == ring->consume)) {
252: if (ring_full(ring)) {
253: return ring->size; /* nothing consumed, but full */
254: } else {
255: return ring_subtract(ring, ring->supply, ring->consume);
256: }
257: } else {
258: return ring_subtract(ring, ring->mark, ring->consume);
259: }
260: }
261:
262: /*
263: * Return the number of CONSECUTIVE bytes available for consuming.
264: * However, don't return more than enough to cross over set mark.
265: */
266: int
267: ring_full_consecutive(ring)
268: Ring *ring;
269: {
270: if ((ring->mark == 0) || (ring->mark == ring->consume)) {
271: if ((ring->supply < ring->consume) || ring_full(ring)) {
272: return ring_subtract(ring, ring->top, ring->consume);
273: } else {
274: return ring_subtract(ring, ring->supply, ring->consume);
275: }
276: } else {
277: if (ring->mark < ring->consume) {
278: return ring_subtract(ring, ring->top, ring->consume);
279: } else { /* Else, distance to mark */
280: return ring_subtract(ring, ring->mark, ring->consume);
281: }
282: }
283: }
284:
285: /*
286: * Move data into the "supply" portion of of the ring buffer.
287: */
288: void
289: ring_supply_data(ring, buffer, count)
290: Ring *ring;
291: unsigned char *buffer;
292: int count;
293: {
294: int i;
295:
296: while (count) {
297: i = MIN(count, ring_empty_consecutive(ring));
1.2 ! niklas 298: memmove(ring->supply, buffer, i);
1.1 deraadt 299: ring_supplied(ring, i);
300: count -= i;
301: buffer += i;
302: }
303: }
304:
305: #ifdef notdef
306:
307: /*
308: * Move data from the "consume" portion of the ring buffer
309: */
310: void
311: ring_consume_data(ring, buffer, count)
312: Ring *ring;
313: unsigned char *buffer;
314: int count;
315: {
316: int i;
317:
318: while (count) {
319: i = MIN(count, ring_full_consecutive(ring));
1.2 ! niklas 320: memmove(buffer, ring->consume, i);
1.1 deraadt 321: ring_consumed(ring, i);
322: count -= i;
323: buffer += i;
324: }
325: }
326: #endif
327: