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