xref: /csrg-svn/usr.bin/telnet/ring.c (revision 32547)
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 
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
4432528Sminshall  * clock, that when the times are EQUAL, then the buffer is FULL.
4532379Sminshall  */
4632379Sminshall static u_long ring_clock = 0;
4732379Sminshall 
4832379Sminshall 
4932528Sminshall #define	ring_empty(d) (((d)->consume == (d)->supply) && \
5032528Sminshall 				((d)->consumetime >= (d)->supplytime))
5132528Sminshall #define	ring_full(d) (((d)->supply == (d)->consume) && \
5232528Sminshall 				((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 
6932528Sminshall     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
8032528Sminshall ring_supplied(ring, count)
8132379Sminshall Ring *ring;
8232379Sminshall int count;
8332379Sminshall {
8432528Sminshall     ring->supply = ring_increment(ring, ring->supply, count);
8532528Sminshall     ring->supplytime = ++ring_clock;
8632379Sminshall }
8732379Sminshall 
8832379Sminshall /*
8932528Sminshall  * We have just consumed "c" bytes.
9032379Sminshall  */
9132379Sminshall void
9232528Sminshall ring_consumed(ring, count)
9332379Sminshall Ring *ring;
9432379Sminshall int count;
9532379Sminshall {
9632528Sminshall     ring->consume = ring_increment(ring, ring->consume, count);
9732528Sminshall     ring->consumetime = ++ring_clock;
98*32547Sminshall     /*
99*32547Sminshall      * Try to encourage "ring_empty_consecutive()" to be large.
100*32547Sminshall      */
101*32547Sminshall     if (ring_empty(ring)) {
102*32547Sminshall 	ring->consume = ring->supply = ring->bottom;
103*32547Sminshall     }
10432379Sminshall }
10532379Sminshall 
10632379Sminshall 
10732379Sminshall 
10832379Sminshall /* Buffer state query routines */
10932379Sminshall 
11032379Sminshall 
11132528Sminshall /* Number of bytes that may be supplied */
11232379Sminshall int
11332379Sminshall ring_empty_count(ring)
11432379Sminshall Ring *ring;
11532379Sminshall {
11632528Sminshall     if (ring_empty(ring)) {	/* if empty */
11732379Sminshall 	    return ring->size;
11832379Sminshall     } else {
11932528Sminshall 	return ring_subtract(ring, ring->consume, ring->supply);
12032379Sminshall     }
12132379Sminshall }
12232379Sminshall 
12332528Sminshall /* number of CONSECUTIVE bytes that may be supplied */
12432379Sminshall int
12532379Sminshall ring_empty_consecutive(ring)
12632379Sminshall Ring *ring;
12732379Sminshall {
12832528Sminshall     if ((ring->consume < ring->supply) || ring_empty(ring)) {
12932528Sminshall 			    /*
13032528Sminshall 			     * if consume is "below" supply, or empty, then
13132528Sminshall 			     * return distance to the top
13232528Sminshall 			     */
13332528Sminshall 	return ring_subtract(ring, ring->top, ring->supply);
13432379Sminshall     } else {
13532379Sminshall 				    /*
13632379Sminshall 				     * else, return what we may.
13732379Sminshall 				     */
13832528Sminshall 	return ring_subtract(ring, ring->consume, ring->supply);
13932379Sminshall     }
14032379Sminshall }
14132379Sminshall 
14232528Sminshall /* number of bytes that are available for consuming */
14332379Sminshall int
14432528Sminshall ring_full_count(ring)
14532379Sminshall Ring *ring;
14632379Sminshall {
14732528Sminshall     if (ring_full(ring)) {
14832528Sminshall 	return ring->size;	/* nothing consumed, but full */
14932379Sminshall     } else {
15032528Sminshall 	return ring_subtract(ring, ring->supply, ring->consume);
15132379Sminshall     }
15232379Sminshall }
15332379Sminshall 
15432528Sminshall /* number of CONSECUTIVE bytes available for consuming */
15532379Sminshall int
15632528Sminshall ring_full_consecutive(ring)
15732379Sminshall Ring *ring;
15832379Sminshall {
15932528Sminshall     if ((ring->supply < ring->consume) || ring_full(ring)) {
16032528Sminshall 	return ring_subtract(ring, ring->top, ring->consume);
16132379Sminshall     } else {
16232528Sminshall 	return ring_subtract(ring, ring->supply, ring->consume);
16332379Sminshall     }
16432379Sminshall }
16532379Sminshall 
16632379Sminshall /*
16732528Sminshall  * Move data into the "supply" portion of of the ring buffer.
16832379Sminshall  */
16932379Sminshall void
17032528Sminshall ring_supply_data(ring, buffer, count)
17132379Sminshall Ring *ring;
17232379Sminshall char *buffer;
17332379Sminshall int count;
17432379Sminshall {
17532379Sminshall     int i;
17632379Sminshall 
17732379Sminshall     while (count) {
17832381Sminshall 	i = MIN(count, ring_empty_consecutive(ring));
17932528Sminshall 	memcpy(ring->supply, buffer, i);
18032528Sminshall 	ring_supplied(ring, i);
18132379Sminshall 	count -= i;
18232379Sminshall 	buffer += i;
18332379Sminshall     }
18432379Sminshall }
18532379Sminshall 
18632379Sminshall 
18732379Sminshall /*
18832528Sminshall  * Move data from the "consume" portion of the ring buffer
18932379Sminshall  */
19032379Sminshall void
19132528Sminshall ring_consume_data(ring, buffer, count)
19232379Sminshall Ring *ring;
19332379Sminshall char *buffer;
19432379Sminshall int count;
19532379Sminshall {
19632379Sminshall     int i;
19732379Sminshall 
19832379Sminshall     while (count) {
19932528Sminshall 	i = MIN(count, ring_full_consecutive(ring));
20032528Sminshall 	memcpy(buffer, ring->consume, i);
20132528Sminshall 	ring_consumed(ring, i);
20232379Sminshall 	count -= i;
20332379Sminshall 	buffer += i;
20432379Sminshall     }
20532379Sminshall }
20632381Sminshall 
20732381Sminshall /* Mark routines */
20832381Sminshall 
20932381Sminshall /* XXX do something here */
21032381Sminshall void
21132381Sminshall ring_mark(ring)
21232381Sminshall Ring *ring;
21332381Sminshall {
21432381Sminshall }
21532381Sminshall 
21632381Sminshall int
21732381Sminshall ring_at_mark(ring)
21832381Sminshall Ring *ring;
21932381Sminshall {
22032381Sminshall     return 0;
22132381Sminshall }
22232381Sminshall 
22332381Sminshall void
22432381Sminshall ring_clear_mark(ring)
22532381Sminshall Ring *ring;
22632381Sminshall {
22732381Sminshall }
228