xref: /csrg-svn/usr.bin/telnet/ring.c (revision 33294)
132379Sminshall /*
232528Sminshall  * This defines a structure for a ring buffer.
332379Sminshall  *
432528Sminshall  * The circular buffer has two parts:
532379Sminshall  *(((
632528Sminshall  *	full:	[consume, supply)
732528Sminshall  *	empty:	[supply, consume)
832379Sminshall  *]]]
932379Sminshall  *
1032379Sminshall  */
1132379Sminshall 
1232379Sminshall #include	<stdio.h>
1332379Sminshall #include	<errno.h>
1432379Sminshall 
1532379Sminshall #ifdef	size_t
1632379Sminshall #undef	size_t
1732379Sminshall #endif
1832379Sminshall 
1932379Sminshall #include	<sys/types.h>
2032379Sminshall #include	<sys/ioctl.h>
2132379Sminshall #include	<sys/socket.h>
2232379Sminshall 
2332379Sminshall #include	"ring.h"
2432379Sminshall #include	"general.h"
2532379Sminshall 
2632379Sminshall /* Internal macros */
2732379Sminshall 
2832381Sminshall #if	!defined(MIN)
2932381Sminshall #define	MIN(a,b)	(((a)<(b))? (a):(b))
3032381Sminshall #endif	/* !defined(MIN) */
3132379Sminshall 
3232381Sminshall #define	ring_subtract(d,a,b)	((((int)(a))-((int)(b)) >= 0)? \
3332381Sminshall 					(a)-(b): (((a)-(b))+(d)->size))
3432379Sminshall 
3532379Sminshall #define	ring_increment(d,a,c)	(((a)+(c) < (d)->top)? \
3632379Sminshall 					(a)+(c) : (((a)+(c))-(d)->size))
3732379Sminshall 
38*33294Sminshall #define	ring_decrement(d,a,c)	(((a)-(c) >= (d)->bottom)? \
39*33294Sminshall 					(a)-(c) : (((a)-(c))-(d)->size))
4032379Sminshall 
41*33294Sminshall 
4232379Sminshall /*
4332379Sminshall  * The following is a clock, used to determine full, empty, etc.
4432379Sminshall  *
4532379Sminshall  * There is some trickiness here.  Since the ring buffers are initialized
4632379Sminshall  * to ZERO on allocation, we need to make sure, when interpreting the
4732528Sminshall  * clock, that when the times are EQUAL, then the buffer is FULL.
4832379Sminshall  */
4932379Sminshall static u_long ring_clock = 0;
5032379Sminshall 
5132379Sminshall 
5232528Sminshall #define	ring_empty(d) (((d)->consume == (d)->supply) && \
5332528Sminshall 				((d)->consumetime >= (d)->supplytime))
5432528Sminshall #define	ring_full(d) (((d)->supply == (d)->consume) && \
5532528Sminshall 				((d)->supplytime > (d)->consumetime))
5632379Sminshall 
5732379Sminshall 
5832379Sminshall 
5932379Sminshall 
6032379Sminshall 
6132379Sminshall /* Buffer state transition routines */
6232379Sminshall 
6332381Sminshall ring_init(ring, buffer, count)
6432381Sminshall Ring *ring;
6532381Sminshall char *buffer;
6632381Sminshall int count;
6732381Sminshall {
6832381Sminshall     memset((char *)ring, 0, sizeof *ring);
6932379Sminshall 
7032381Sminshall     ring->size = count;
7132381Sminshall 
7232528Sminshall     ring->supply = ring->consume = ring->bottom = buffer;
7332381Sminshall 
7432381Sminshall     ring->top = ring->bottom+ring->size;
7532381Sminshall 
7632381Sminshall     return 1;
7732381Sminshall }
7832381Sminshall 
79*33294Sminshall /* Mark routines */
80*33294Sminshall 
8132379Sminshall /*
82*33294Sminshall  * Mark the most recently supplied byte.
83*33294Sminshall  */
84*33294Sminshall 
85*33294Sminshall void
86*33294Sminshall ring_mark(ring)
87*33294Sminshall Ring *ring;
88*33294Sminshall {
89*33294Sminshall     ring->mark = ring_decrement(ring, ring->supply, 1);
90*33294Sminshall }
91*33294Sminshall 
92*33294Sminshall /*
93*33294Sminshall  * Is the ring pointing to the mark?
94*33294Sminshall  */
95*33294Sminshall 
96*33294Sminshall int
97*33294Sminshall ring_at_mark(ring)
98*33294Sminshall Ring *ring;
99*33294Sminshall {
100*33294Sminshall     if (ring->mark == ring->consume) {
101*33294Sminshall 	return 1;
102*33294Sminshall     } else {
103*33294Sminshall 	return 0;
104*33294Sminshall     }
105*33294Sminshall }
106*33294Sminshall 
107*33294Sminshall /*
108*33294Sminshall  * Clear any mark set on the ring.
109*33294Sminshall  */
110*33294Sminshall 
111*33294Sminshall void
112*33294Sminshall ring_clear_mark(ring)
113*33294Sminshall Ring *ring;
114*33294Sminshall {
115*33294Sminshall     ring->mark = 0;
116*33294Sminshall }
117*33294Sminshall 
118*33294Sminshall /*
11932379Sminshall  * Add characters from current segment to ring buffer.
12032379Sminshall  */
12132379Sminshall void
12232528Sminshall ring_supplied(ring, count)
12332379Sminshall Ring *ring;
12432379Sminshall int count;
12532379Sminshall {
12632528Sminshall     ring->supply = ring_increment(ring, ring->supply, count);
12732528Sminshall     ring->supplytime = ++ring_clock;
12832379Sminshall }
12932379Sminshall 
13032379Sminshall /*
13132528Sminshall  * We have just consumed "c" bytes.
13232379Sminshall  */
13332379Sminshall void
13432528Sminshall ring_consumed(ring, count)
13532379Sminshall Ring *ring;
13632379Sminshall int count;
13732379Sminshall {
13832667Sminshall     if (count == 0)	/* don't update anything */
13932667Sminshall 	return;
14032667Sminshall 
141*33294Sminshall     if (ring->mark &&
142*33294Sminshall 		(ring_subtract(ring, ring->mark, ring->consume) < count)) {
143*33294Sminshall 	ring->mark = 0;
144*33294Sminshall     }
14532528Sminshall     ring->consume = ring_increment(ring, ring->consume, count);
14632528Sminshall     ring->consumetime = ++ring_clock;
14732547Sminshall     /*
14832547Sminshall      * Try to encourage "ring_empty_consecutive()" to be large.
14932547Sminshall      */
15032547Sminshall     if (ring_empty(ring)) {
15132547Sminshall 	ring->consume = ring->supply = ring->bottom;
15232547Sminshall     }
15332379Sminshall }
15432379Sminshall 
15532379Sminshall 
15632379Sminshall 
15732379Sminshall /* Buffer state query routines */
15832379Sminshall 
15932379Sminshall 
16032528Sminshall /* Number of bytes that may be supplied */
16132379Sminshall int
16232379Sminshall ring_empty_count(ring)
16332379Sminshall Ring *ring;
16432379Sminshall {
16532528Sminshall     if (ring_empty(ring)) {	/* if empty */
16632379Sminshall 	    return ring->size;
16732379Sminshall     } else {
16832528Sminshall 	return ring_subtract(ring, ring->consume, ring->supply);
16932379Sminshall     }
17032379Sminshall }
17132379Sminshall 
17232528Sminshall /* number of CONSECUTIVE bytes that may be supplied */
17332379Sminshall int
17432379Sminshall ring_empty_consecutive(ring)
17532379Sminshall Ring *ring;
17632379Sminshall {
17732528Sminshall     if ((ring->consume < ring->supply) || ring_empty(ring)) {
17832528Sminshall 			    /*
17932528Sminshall 			     * if consume is "below" supply, or empty, then
18032528Sminshall 			     * return distance to the top
18132528Sminshall 			     */
18232528Sminshall 	return ring_subtract(ring, ring->top, ring->supply);
18332379Sminshall     } else {
18432379Sminshall 				    /*
18532379Sminshall 				     * else, return what we may.
18632379Sminshall 				     */
18732528Sminshall 	return ring_subtract(ring, ring->consume, ring->supply);
18832379Sminshall     }
18932379Sminshall }
19032379Sminshall 
191*33294Sminshall /* Return the number of bytes that are available for consuming
192*33294Sminshall  * (but don't give more than enough to get to cross over set mark)
193*33294Sminshall  */
194*33294Sminshall 
19532379Sminshall int
19632528Sminshall ring_full_count(ring)
19732379Sminshall Ring *ring;
19832379Sminshall {
199*33294Sminshall     if ((ring->mark == 0) || (ring->mark == ring->consume)) {
200*33294Sminshall 	if (ring_full(ring)) {
201*33294Sminshall 	    return ring->size;	/* nothing consumed, but full */
202*33294Sminshall 	} else {
203*33294Sminshall 	    return ring_subtract(ring, ring->supply, ring->consume);
204*33294Sminshall 	}
20532379Sminshall     } else {
206*33294Sminshall 	return ring_subtract(ring, ring->mark, ring->consume);
20732379Sminshall     }
20832379Sminshall }
20932379Sminshall 
210*33294Sminshall /*
211*33294Sminshall  * Return the number of CONSECUTIVE bytes available for consuming.
212*33294Sminshall  * However, don't return more than enough to cross over set mark.
213*33294Sminshall  */
21432379Sminshall int
21532528Sminshall ring_full_consecutive(ring)
21632379Sminshall Ring *ring;
21732379Sminshall {
218*33294Sminshall     if ((ring->mark == 0) || (ring->mark == ring->consume)) {
219*33294Sminshall 	if ((ring->supply < ring->consume) || ring_full(ring)) {
220*33294Sminshall 	    return ring_subtract(ring, ring->top, ring->consume);
221*33294Sminshall 	} else {
222*33294Sminshall 	    return ring_subtract(ring, ring->supply, ring->consume);
223*33294Sminshall 	}
22432379Sminshall     } else {
225*33294Sminshall 	if (ring->mark < ring->consume) {
226*33294Sminshall 	    return ring_subtract(ring, ring->top, ring->consume);
227*33294Sminshall 	} else {	/* Else, distance to mark */
228*33294Sminshall 	    return ring_subtract(ring, ring->mark, ring->consume);
229*33294Sminshall 	}
23032379Sminshall     }
23132379Sminshall }
23232379Sminshall 
23332379Sminshall /*
23432528Sminshall  * Move data into the "supply" portion of of the ring buffer.
23532379Sminshall  */
23632379Sminshall void
23732528Sminshall ring_supply_data(ring, buffer, count)
23832379Sminshall Ring *ring;
23932379Sminshall char *buffer;
24032379Sminshall int count;
24132379Sminshall {
24232379Sminshall     int i;
24332379Sminshall 
24432379Sminshall     while (count) {
24532381Sminshall 	i = MIN(count, ring_empty_consecutive(ring));
24632528Sminshall 	memcpy(ring->supply, buffer, i);
24732528Sminshall 	ring_supplied(ring, i);
24832379Sminshall 	count -= i;
24932379Sminshall 	buffer += i;
25032379Sminshall     }
25132379Sminshall }
25232379Sminshall 
25332379Sminshall 
25432379Sminshall /*
25532528Sminshall  * Move data from the "consume" portion of the ring buffer
25632379Sminshall  */
25732379Sminshall void
25832528Sminshall ring_consume_data(ring, buffer, count)
25932379Sminshall Ring *ring;
26032379Sminshall char *buffer;
26132379Sminshall int count;
26232379Sminshall {
26332379Sminshall     int i;
26432379Sminshall 
26532379Sminshall     while (count) {
26632528Sminshall 	i = MIN(count, ring_full_consecutive(ring));
26732528Sminshall 	memcpy(buffer, ring->consume, i);
26832528Sminshall 	ring_consumed(ring, i);
26932379Sminshall 	count -= i;
27032379Sminshall 	buffer += i;
27132379Sminshall     }
27232379Sminshall }
273