Annotation of src/usr.bin/telnet/ring.c, Revision 1.8
1.8 ! guenther 1: /* $OpenBSD: ring.c,v 1.7 2014/07/20 06:24:19 guenther Exp $ */
1.2 niklas 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.
1.5 millert 16: * 3. Neither the name of the University nor the names of its contributors
1.1 deraadt 17: * may be used to endorse or promote products derived from this software
18: * without specific prior written permission.
19: *
20: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30: * SUCH DAMAGE.
31: */
32:
1.8 ! guenther 33: #include <string.h>
! 34: #include "ring.h"
1.1 deraadt 35:
36: /*
37: * This defines a structure for a ring buffer.
38: *
39: * The circular buffer has two parts:
40: *(((
41: * full: [consume, supply)
42: * empty: [supply, consume)
43: *]]]
44: *
45: */
46:
47: /* Internal macros */
48:
49: #if !defined(MIN)
50: #define MIN(a,b) (((a)<(b))? (a):(b))
51: #endif /* !defined(MIN) */
52:
53: #define ring_subtract(d,a,b) (((a)-(b) >= 0)? \
54: (a)-(b): (((a)-(b))+(d)->size))
55:
56: #define ring_increment(d,a,c) (((a)+(c) < (d)->top)? \
57: (a)+(c) : (((a)+(c))-(d)->size))
58:
59: #define ring_decrement(d,a,c) (((a)-(c) >= (d)->bottom)? \
60: (a)-(c) : (((a)-(c))-(d)->size))
61:
62:
63: /*
64: * The following is a clock, used to determine full, empty, etc.
65: *
66: * There is some trickiness here. Since the ring buffers are initialized
67: * to ZERO on allocation, we need to make sure, when interpreting the
68: * clock, that when the times are EQUAL, then the buffer is FULL.
69: */
1.8 ! guenther 70: static unsigned long ring_clock = 0;
1.1 deraadt 71:
72:
73: #define ring_empty(d) (((d)->consume == (d)->supply) && \
74: ((d)->consumetime >= (d)->supplytime))
75: #define ring_full(d) (((d)->supply == (d)->consume) && \
76: ((d)->supplytime > (d)->consumetime))
77:
78:
79:
80:
81:
82: /* Buffer state transition routines */
83:
1.7 guenther 84: void
1.4 art 85: ring_init(ring, buffer, count)
86: Ring *ring;
1.1 deraadt 87: unsigned char *buffer;
88: int count;
89: {
1.7 guenther 90: memset(ring, 0, sizeof *ring);
1.1 deraadt 91:
92: ring->size = count;
93:
94: ring->supply = ring->consume = ring->bottom = buffer;
95:
96: ring->top = ring->bottom+ring->size;
97: }
98:
99: /* Mark routines */
100:
101: /*
102: * Mark the most recently supplied byte.
103: */
104:
105: void
106: ring_mark(ring)
107: Ring *ring;
108: {
109: ring->mark = ring_decrement(ring, ring->supply, 1);
110: }
111:
112: /*
113: * Is the ring pointing to the mark?
114: */
115:
116: int
117: ring_at_mark(ring)
118: Ring *ring;
119: {
120: if (ring->mark == ring->consume) {
121: return 1;
122: } else {
123: return 0;
124: }
125: }
126:
127: /*
128: * Clear any mark set on the ring.
129: */
130:
131: void
132: ring_clear_mark(ring)
133: Ring *ring;
134: {
135: ring->mark = 0;
136: }
137:
138: /*
139: * Add characters from current segment to ring buffer.
140: */
141: void
142: ring_supplied(ring, count)
143: Ring *ring;
144: int count;
145: {
146: ring->supply = ring_increment(ring, ring->supply, count);
147: ring->supplytime = ++ring_clock;
148: }
149:
150: /*
151: * We have just consumed "c" bytes.
152: */
153: void
154: ring_consumed(ring, count)
155: Ring *ring;
156: int count;
157: {
158: if (count == 0) /* don't update anything */
159: return;
160:
161: if (ring->mark &&
162: (ring_subtract(ring, ring->mark, ring->consume) < count)) {
163: ring->mark = 0;
164: }
165: ring->consume = ring_increment(ring, ring->consume, count);
166: ring->consumetime = ++ring_clock;
167: /*
168: * Try to encourage "ring_empty_consecutive()" to be large.
169: */
170: if (ring_empty(ring)) {
171: ring->consume = ring->supply = ring->bottom;
172: }
173: }
174:
175:
176:
177: /* Buffer state query routines */
178:
179:
180: /* Number of bytes that may be supplied */
181: int
182: ring_empty_count(ring)
183: Ring *ring;
184: {
185: if (ring_empty(ring)) { /* if empty */
186: return ring->size;
187: } else {
188: return ring_subtract(ring, ring->consume, ring->supply);
189: }
190: }
191:
192: /* number of CONSECUTIVE bytes that may be supplied */
193: int
194: ring_empty_consecutive(ring)
195: Ring *ring;
196: {
197: if ((ring->consume < ring->supply) || ring_empty(ring)) {
198: /*
199: * if consume is "below" supply, or empty, then
200: * return distance to the top
201: */
202: return ring_subtract(ring, ring->top, ring->supply);
203: } else {
204: /*
205: * else, return what we may.
206: */
207: return ring_subtract(ring, ring->consume, ring->supply);
208: }
209: }
210:
211: /* Return the number of bytes that are available for consuming
212: * (but don't give more than enough to get to cross over set mark)
213: */
214:
215: int
216: ring_full_count(ring)
217: Ring *ring;
218: {
219: if ((ring->mark == 0) || (ring->mark == ring->consume)) {
220: if (ring_full(ring)) {
221: return ring->size; /* nothing consumed, but full */
222: } else {
223: return ring_subtract(ring, ring->supply, ring->consume);
224: }
225: } else {
226: return ring_subtract(ring, ring->mark, ring->consume);
227: }
228: }
229:
230: /*
231: * Return the number of CONSECUTIVE bytes available for consuming.
232: * However, don't return more than enough to cross over set mark.
233: */
234: int
235: ring_full_consecutive(ring)
236: Ring *ring;
237: {
238: if ((ring->mark == 0) || (ring->mark == ring->consume)) {
239: if ((ring->supply < ring->consume) || ring_full(ring)) {
240: return ring_subtract(ring, ring->top, ring->consume);
241: } else {
242: return ring_subtract(ring, ring->supply, ring->consume);
243: }
244: } else {
245: if (ring->mark < ring->consume) {
246: return ring_subtract(ring, ring->top, ring->consume);
247: } else { /* Else, distance to mark */
248: return ring_subtract(ring, ring->mark, ring->consume);
249: }
250: }
251: }
252:
253: /*
254: * Move data into the "supply" portion of of the ring buffer.
255: */
256: void
257: ring_supply_data(ring, buffer, count)
258: Ring *ring;
259: unsigned char *buffer;
260: int count;
261: {
262: int i;
263:
264: while (count) {
265: i = MIN(count, ring_empty_consecutive(ring));
1.2 niklas 266: memmove(ring->supply, buffer, i);
1.1 deraadt 267: ring_supplied(ring, i);
268: count -= i;
269: buffer += i;
270: }
271: }