xref: /csrg-svn/usr.bin/telnet/ring.c (revision 32528)
132379Sminshall /*
2*32528Sminshall  * This defines a structure for a ring buffer.
332379Sminshall  *
4*32528Sminshall  * The circular buffer has two parts:
532379Sminshall  *(((
6*32528Sminshall  *	full:	[consume, supply)
7*32528Sminshall  *	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 
3832379Sminshall 
3932379Sminshall /*
4032379Sminshall  * The following is a clock, used to determine full, empty, etc.
4132379Sminshall  *
4232379Sminshall  * There is some trickiness here.  Since the ring buffers are initialized
4332379Sminshall  * to ZERO on allocation, we need to make sure, when interpreting the
44*32528Sminshall  * clock, that when the times are EQUAL, then the buffer is FULL.
4532379Sminshall  */
4632379Sminshall static u_long ring_clock = 0;
4732379Sminshall 
4832379Sminshall 
49*32528Sminshall #define	ring_empty(d) (((d)->consume == (d)->supply) && \
50*32528Sminshall 				((d)->consumetime >= (d)->supplytime))
51*32528Sminshall #define	ring_full(d) (((d)->supply == (d)->consume) && \
52*32528Sminshall 				((d)->supplytime > (d)->consumetime))
5332379Sminshall 
5432379Sminshall 
5532379Sminshall 
5632379Sminshall 
5732379Sminshall 
5832379Sminshall /* Buffer state transition routines */
5932379Sminshall 
6032381Sminshall ring_init(ring, buffer, count)
6132381Sminshall Ring *ring;
6232381Sminshall char *buffer;
6332381Sminshall int count;
6432381Sminshall {
6532381Sminshall     memset((char *)ring, 0, sizeof *ring);
6632379Sminshall 
6732381Sminshall     ring->size = count;
6832381Sminshall 
69*32528Sminshall     ring->supply = ring->consume = ring->bottom = buffer;
7032381Sminshall 
7132381Sminshall     ring->top = ring->bottom+ring->size;
7232381Sminshall 
7332381Sminshall     return 1;
7432381Sminshall }
7532381Sminshall 
7632379Sminshall /*
7732379Sminshall  * Add characters from current segment to ring buffer.
7832379Sminshall  */
7932379Sminshall void
80*32528Sminshall ring_supplied(ring, count)
8132379Sminshall Ring *ring;
8232379Sminshall int count;
8332379Sminshall {
84*32528Sminshall     ring->supply = ring_increment(ring, ring->supply, count);
85*32528Sminshall     ring->supplytime = ++ring_clock;
8632379Sminshall }
8732379Sminshall 
8832379Sminshall /*
89*32528Sminshall  * We have just consumed "c" bytes.
9032379Sminshall  */
9132379Sminshall void
92*32528Sminshall ring_consumed(ring, count)
9332379Sminshall Ring *ring;
9432379Sminshall int count;
9532379Sminshall {
96*32528Sminshall     ring->consume = ring_increment(ring, ring->consume, count);
97*32528Sminshall     ring->consumetime = ++ring_clock;
9832379Sminshall }
9932379Sminshall 
10032379Sminshall 
10132379Sminshall 
10232379Sminshall /* Buffer state query routines */
10332379Sminshall 
10432379Sminshall 
105*32528Sminshall /* Number of bytes that may be supplied */
10632379Sminshall int
10732379Sminshall ring_empty_count(ring)
10832379Sminshall Ring *ring;
10932379Sminshall {
110*32528Sminshall     if (ring_empty(ring)) {	/* if empty */
11132379Sminshall 	    return ring->size;
11232379Sminshall     } else {
113*32528Sminshall 	return ring_subtract(ring, ring->consume, ring->supply);
11432379Sminshall     }
11532379Sminshall }
11632379Sminshall 
117*32528Sminshall /* number of CONSECUTIVE bytes that may be supplied */
11832379Sminshall int
11932379Sminshall ring_empty_consecutive(ring)
12032379Sminshall Ring *ring;
12132379Sminshall {
122*32528Sminshall     if ((ring->consume < ring->supply) || ring_empty(ring)) {
123*32528Sminshall 			    /*
124*32528Sminshall 			     * if consume is "below" supply, or empty, then
125*32528Sminshall 			     * return distance to the top
126*32528Sminshall 			     */
127*32528Sminshall 	return ring_subtract(ring, ring->top, ring->supply);
12832379Sminshall     } else {
12932379Sminshall 				    /*
13032379Sminshall 				     * else, return what we may.
13132379Sminshall 				     */
132*32528Sminshall 	return ring_subtract(ring, ring->consume, ring->supply);
13332379Sminshall     }
13432379Sminshall }
13532379Sminshall 
136*32528Sminshall /* number of bytes that are available for consuming */
13732379Sminshall int
138*32528Sminshall ring_full_count(ring)
13932379Sminshall Ring *ring;
14032379Sminshall {
141*32528Sminshall     if (ring_full(ring)) {
142*32528Sminshall 	return ring->size;	/* nothing consumed, but full */
14332379Sminshall     } else {
144*32528Sminshall 	return ring_subtract(ring, ring->supply, ring->consume);
14532379Sminshall     }
14632379Sminshall }
14732379Sminshall 
148*32528Sminshall /* number of CONSECUTIVE bytes available for consuming */
14932379Sminshall int
150*32528Sminshall ring_full_consecutive(ring)
15132379Sminshall Ring *ring;
15232379Sminshall {
153*32528Sminshall     if ((ring->supply < ring->consume) || ring_full(ring)) {
154*32528Sminshall 	return ring_subtract(ring, ring->top, ring->consume);
15532379Sminshall     } else {
156*32528Sminshall 	return ring_subtract(ring, ring->supply, ring->consume);
15732379Sminshall     }
15832379Sminshall }
15932379Sminshall 
16032379Sminshall /*
161*32528Sminshall  * Move data into the "supply" portion of of the ring buffer.
16232379Sminshall  */
16332379Sminshall void
164*32528Sminshall ring_supply_data(ring, buffer, count)
16532379Sminshall Ring *ring;
16632379Sminshall char *buffer;
16732379Sminshall int count;
16832379Sminshall {
16932379Sminshall     int i;
17032379Sminshall 
17132379Sminshall     while (count) {
17232381Sminshall 	i = MIN(count, ring_empty_consecutive(ring));
173*32528Sminshall 	memcpy(ring->supply, buffer, i);
174*32528Sminshall 	ring_supplied(ring, i);
17532379Sminshall 	count -= i;
17632379Sminshall 	buffer += i;
17732379Sminshall     }
17832379Sminshall }
17932379Sminshall 
18032379Sminshall 
18132379Sminshall /*
182*32528Sminshall  * Move data from the "consume" portion of the ring buffer
18332379Sminshall  */
18432379Sminshall void
185*32528Sminshall ring_consume_data(ring, buffer, count)
18632379Sminshall Ring *ring;
18732379Sminshall char *buffer;
18832379Sminshall int count;
18932379Sminshall {
19032379Sminshall     int i;
19132379Sminshall 
19232379Sminshall     while (count) {
193*32528Sminshall 	i = MIN(count, ring_full_consecutive(ring));
194*32528Sminshall 	memcpy(buffer, ring->consume, i);
195*32528Sminshall 	ring_consumed(ring, i);
19632379Sminshall 	count -= i;
19732379Sminshall 	buffer += i;
19832379Sminshall     }
19932379Sminshall }
20032381Sminshall 
20132381Sminshall /* Mark routines */
20232381Sminshall 
20332381Sminshall /* XXX do something here */
20432381Sminshall void
20532381Sminshall ring_mark(ring)
20632381Sminshall Ring *ring;
20732381Sminshall {
20832381Sminshall }
20932381Sminshall 
21032381Sminshall int
21132381Sminshall ring_at_mark(ring)
21232381Sminshall Ring *ring;
21332381Sminshall {
21432381Sminshall     return 0;
21532381Sminshall }
21632381Sminshall 
21732381Sminshall void
21832381Sminshall ring_clear_mark(ring)
21932381Sminshall Ring *ring;
22032381Sminshall {
22132381Sminshall }
222