Annotation of src/usr.bin/telnet/ring.c, Revision 1.7
1.7 ! guenther 1: /* $OpenBSD: ring.c,v 1.6 2014/07/19 23:50:38 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.3 art 33: #include "telnet_locl.h"
1.1 deraadt 34:
35: /*
36: * This defines a structure for a ring buffer.
37: *
38: * The circular buffer has two parts:
39: *(((
40: * full: [consume, supply)
41: * empty: [supply, consume)
42: *]]]
43: *
44: */
45:
46: /* Internal macros */
47:
48: #if !defined(MIN)
49: #define MIN(a,b) (((a)<(b))? (a):(b))
50: #endif /* !defined(MIN) */
51:
52: #define ring_subtract(d,a,b) (((a)-(b) >= 0)? \
53: (a)-(b): (((a)-(b))+(d)->size))
54:
55: #define ring_increment(d,a,c) (((a)+(c) < (d)->top)? \
56: (a)+(c) : (((a)+(c))-(d)->size))
57:
58: #define ring_decrement(d,a,c) (((a)-(c) >= (d)->bottom)? \
59: (a)-(c) : (((a)-(c))-(d)->size))
60:
61:
62: /*
63: * The following is a clock, used to determine full, empty, etc.
64: *
65: * There is some trickiness here. Since the ring buffers are initialized
66: * to ZERO on allocation, we need to make sure, when interpreting the
67: * clock, that when the times are EQUAL, then the buffer is FULL.
68: */
69: static u_long ring_clock = 0;
70:
71:
72: #define ring_empty(d) (((d)->consume == (d)->supply) && \
73: ((d)->consumetime >= (d)->supplytime))
74: #define ring_full(d) (((d)->supply == (d)->consume) && \
75: ((d)->supplytime > (d)->consumetime))
76:
77:
78:
79:
80:
81: /* Buffer state transition routines */
82:
1.7 ! guenther 83: void
1.4 art 84: ring_init(ring, buffer, count)
85: Ring *ring;
1.1 deraadt 86: unsigned char *buffer;
87: int count;
88: {
1.7 ! guenther 89: memset(ring, 0, sizeof *ring);
1.1 deraadt 90:
91: ring->size = count;
92:
93: ring->supply = ring->consume = ring->bottom = buffer;
94:
95: ring->top = ring->bottom+ring->size;
96: }
97:
98: /* Mark routines */
99:
100: /*
101: * Mark the most recently supplied byte.
102: */
103:
104: void
105: ring_mark(ring)
106: Ring *ring;
107: {
108: ring->mark = ring_decrement(ring, ring->supply, 1);
109: }
110:
111: /*
112: * Is the ring pointing to the mark?
113: */
114:
115: int
116: ring_at_mark(ring)
117: Ring *ring;
118: {
119: if (ring->mark == ring->consume) {
120: return 1;
121: } else {
122: return 0;
123: }
124: }
125:
126: /*
127: * Clear any mark set on the ring.
128: */
129:
130: void
131: ring_clear_mark(ring)
132: Ring *ring;
133: {
134: ring->mark = 0;
135: }
136:
137: /*
138: * Add characters from current segment to ring buffer.
139: */
140: void
141: ring_supplied(ring, count)
142: Ring *ring;
143: int count;
144: {
145: ring->supply = ring_increment(ring, ring->supply, count);
146: ring->supplytime = ++ring_clock;
147: }
148:
149: /*
150: * We have just consumed "c" bytes.
151: */
152: void
153: ring_consumed(ring, count)
154: Ring *ring;
155: int count;
156: {
157: if (count == 0) /* don't update anything */
158: return;
159:
160: if (ring->mark &&
161: (ring_subtract(ring, ring->mark, ring->consume) < count)) {
162: ring->mark = 0;
163: }
164: ring->consume = ring_increment(ring, ring->consume, count);
165: ring->consumetime = ++ring_clock;
166: /*
167: * Try to encourage "ring_empty_consecutive()" to be large.
168: */
169: if (ring_empty(ring)) {
170: ring->consume = ring->supply = ring->bottom;
171: }
172: }
173:
174:
175:
176: /* Buffer state query routines */
177:
178:
179: /* Number of bytes that may be supplied */
180: int
181: ring_empty_count(ring)
182: Ring *ring;
183: {
184: if (ring_empty(ring)) { /* if empty */
185: return ring->size;
186: } else {
187: return ring_subtract(ring, ring->consume, ring->supply);
188: }
189: }
190:
191: /* number of CONSECUTIVE bytes that may be supplied */
192: int
193: ring_empty_consecutive(ring)
194: Ring *ring;
195: {
196: if ((ring->consume < ring->supply) || ring_empty(ring)) {
197: /*
198: * if consume is "below" supply, or empty, then
199: * return distance to the top
200: */
201: return ring_subtract(ring, ring->top, ring->supply);
202: } else {
203: /*
204: * else, return what we may.
205: */
206: return ring_subtract(ring, ring->consume, ring->supply);
207: }
208: }
209:
210: /* Return the number of bytes that are available for consuming
211: * (but don't give more than enough to get to cross over set mark)
212: */
213:
214: int
215: ring_full_count(ring)
216: Ring *ring;
217: {
218: if ((ring->mark == 0) || (ring->mark == ring->consume)) {
219: if (ring_full(ring)) {
220: return ring->size; /* nothing consumed, but full */
221: } else {
222: return ring_subtract(ring, ring->supply, ring->consume);
223: }
224: } else {
225: return ring_subtract(ring, ring->mark, ring->consume);
226: }
227: }
228:
229: /*
230: * Return the number of CONSECUTIVE bytes available for consuming.
231: * However, don't return more than enough to cross over set mark.
232: */
233: int
234: ring_full_consecutive(ring)
235: Ring *ring;
236: {
237: if ((ring->mark == 0) || (ring->mark == ring->consume)) {
238: if ((ring->supply < ring->consume) || ring_full(ring)) {
239: return ring_subtract(ring, ring->top, ring->consume);
240: } else {
241: return ring_subtract(ring, ring->supply, ring->consume);
242: }
243: } else {
244: if (ring->mark < ring->consume) {
245: return ring_subtract(ring, ring->top, ring->consume);
246: } else { /* Else, distance to mark */
247: return ring_subtract(ring, ring->mark, ring->consume);
248: }
249: }
250: }
251:
252: /*
253: * Move data into the "supply" portion of of the ring buffer.
254: */
255: void
256: ring_supply_data(ring, buffer, count)
257: Ring *ring;
258: unsigned char *buffer;
259: int count;
260: {
261: int i;
262:
263: while (count) {
264: i = MIN(count, ring_empty_consecutive(ring));
1.2 niklas 265: memmove(ring->supply, buffer, i);
1.1 deraadt 266: ring_supplied(ring, i);
267: count -= i;
268: buffer += i;
269: }
270: }