|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1988 Regents of the University of California. ! 3: * All rights reserved. ! 4: * ! 5: * Redistribution and use in source and binary forms are permitted ! 6: * provided that this notice is preserved and that due credit is given ! 7: * to the University of California at Berkeley. The name of the University ! 8: * may not be used to endorse or promote products derived from this ! 9: * software without specific prior written permission. This software ! 10: * is provided ``as is'' without express or implied warranty. ! 11: */ ! 12: ! 13: #ifndef lint ! 14: static char sccsid[] = "@(#)ring.c 1.8 (Berkeley) 3/8/88"; ! 15: #endif /* not lint */ ! 16: ! 17: /* ! 18: * This defines a structure for a ring buffer. ! 19: * ! 20: * The circular buffer has two parts: ! 21: *((( ! 22: * full: [consume, supply) ! 23: * empty: [supply, consume) ! 24: *]]] ! 25: * ! 26: */ ! 27: ! 28: #include <stdio.h> ! 29: #include <errno.h> ! 30: ! 31: #ifdef size_t ! 32: #undef size_t ! 33: #endif ! 34: ! 35: #include <sys/types.h> ! 36: #include <sys/ioctl.h> ! 37: #include <sys/socket.h> ! 38: ! 39: #include "ring.h" ! 40: #include "general.h" ! 41: ! 42: /* Internal macros */ ! 43: ! 44: #if !defined(MIN) ! 45: #define MIN(a,b) (((a)<(b))? (a):(b)) ! 46: #endif /* !defined(MIN) */ ! 47: ! 48: #define ring_subtract(d,a,b) ((((int)(a))-((int)(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: */ ! 65: static u_long ring_clock = 0; ! 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: ! 79: ring_init(ring, buffer, count) ! 80: Ring *ring; ! 81: char *buffer; ! 82: int count; ! 83: { ! 84: memset((char *)ring, 0, sizeof *ring); ! 85: ! 86: ring->size = count; ! 87: ! 88: ring->supply = ring->consume = ring->bottom = buffer; ! 89: ! 90: ring->top = ring->bottom+ring->size; ! 91: ! 92: return 1; ! 93: } ! 94: ! 95: /* Mark routines */ ! 96: ! 97: /* ! 98: * Mark the most recently supplied byte. ! 99: */ ! 100: ! 101: void ! 102: ring_mark(ring) ! 103: Ring *ring; ! 104: { ! 105: ring->mark = ring_decrement(ring, ring->supply, 1); ! 106: } ! 107: ! 108: /* ! 109: * Is the ring pointing to the mark? ! 110: */ ! 111: ! 112: int ! 113: ring_at_mark(ring) ! 114: Ring *ring; ! 115: { ! 116: if (ring->mark == ring->consume) { ! 117: return 1; ! 118: } else { ! 119: return 0; ! 120: } ! 121: } ! 122: ! 123: /* ! 124: * Clear any mark set on the ring. ! 125: */ ! 126: ! 127: void ! 128: ring_clear_mark(ring) ! 129: Ring *ring; ! 130: { ! 131: ring->mark = 0; ! 132: } ! 133: ! 134: /* ! 135: * Add characters from current segment to ring buffer. ! 136: */ ! 137: void ! 138: ring_supplied(ring, count) ! 139: Ring *ring; ! 140: int count; ! 141: { ! 142: ring->supply = ring_increment(ring, ring->supply, count); ! 143: ring->supplytime = ++ring_clock; ! 144: } ! 145: ! 146: /* ! 147: * We have just consumed "c" bytes. ! 148: */ ! 149: void ! 150: ring_consumed(ring, count) ! 151: Ring *ring; ! 152: int count; ! 153: { ! 154: if (count == 0) /* don't update anything */ ! 155: return; ! 156: ! 157: if (ring->mark && ! 158: (ring_subtract(ring, ring->mark, ring->consume) < count)) { ! 159: ring->mark = 0; ! 160: } ! 161: ring->consume = ring_increment(ring, ring->consume, count); ! 162: ring->consumetime = ++ring_clock; ! 163: /* ! 164: * Try to encourage "ring_empty_consecutive()" to be large. ! 165: */ ! 166: if (ring_empty(ring)) { ! 167: ring->consume = ring->supply = ring->bottom; ! 168: } ! 169: } ! 170: ! 171: ! 172: ! 173: /* Buffer state query routines */ ! 174: ! 175: ! 176: /* Number of bytes that may be supplied */ ! 177: int ! 178: ring_empty_count(ring) ! 179: Ring *ring; ! 180: { ! 181: if (ring_empty(ring)) { /* if empty */ ! 182: return ring->size; ! 183: } else { ! 184: return ring_subtract(ring, ring->consume, ring->supply); ! 185: } ! 186: } ! 187: ! 188: /* number of CONSECUTIVE bytes that may be supplied */ ! 189: int ! 190: ring_empty_consecutive(ring) ! 191: Ring *ring; ! 192: { ! 193: if ((ring->consume < ring->supply) || ring_empty(ring)) { ! 194: /* ! 195: * if consume is "below" supply, or empty, then ! 196: * return distance to the top ! 197: */ ! 198: return ring_subtract(ring, ring->top, ring->supply); ! 199: } else { ! 200: /* ! 201: * else, return what we may. ! 202: */ ! 203: return ring_subtract(ring, ring->consume, ring->supply); ! 204: } ! 205: } ! 206: ! 207: /* Return the number of bytes that are available for consuming ! 208: * (but don't give more than enough to get to cross over set mark) ! 209: */ ! 210: ! 211: int ! 212: ring_full_count(ring) ! 213: Ring *ring; ! 214: { ! 215: if ((ring->mark == 0) || (ring->mark == ring->consume)) { ! 216: if (ring_full(ring)) { ! 217: return ring->size; /* nothing consumed, but full */ ! 218: } else { ! 219: return ring_subtract(ring, ring->supply, ring->consume); ! 220: } ! 221: } else { ! 222: return ring_subtract(ring, ring->mark, ring->consume); ! 223: } ! 224: } ! 225: ! 226: /* ! 227: * Return the number of CONSECUTIVE bytes available for consuming. ! 228: * However, don't return more than enough to cross over set mark. ! 229: */ ! 230: int ! 231: ring_full_consecutive(ring) ! 232: Ring *ring; ! 233: { ! 234: if ((ring->mark == 0) || (ring->mark == ring->consume)) { ! 235: if ((ring->supply < ring->consume) || ring_full(ring)) { ! 236: return ring_subtract(ring, ring->top, ring->consume); ! 237: } else { ! 238: return ring_subtract(ring, ring->supply, ring->consume); ! 239: } ! 240: } else { ! 241: if (ring->mark < ring->consume) { ! 242: return ring_subtract(ring, ring->top, ring->consume); ! 243: } else { /* Else, distance to mark */ ! 244: return ring_subtract(ring, ring->mark, ring->consume); ! 245: } ! 246: } ! 247: } ! 248: ! 249: /* ! 250: * Move data into the "supply" portion of of the ring buffer. ! 251: */ ! 252: void ! 253: ring_supply_data(ring, buffer, count) ! 254: Ring *ring; ! 255: char *buffer; ! 256: int count; ! 257: { ! 258: int i; ! 259: ! 260: while (count) { ! 261: i = MIN(count, ring_empty_consecutive(ring)); ! 262: memcpy(ring->supply, buffer, i); ! 263: ring_supplied(ring, i); ! 264: count -= i; ! 265: buffer += i; ! 266: } ! 267: } ! 268: ! 269: ! 270: /* ! 271: * Move data from the "consume" portion of the ring buffer ! 272: */ ! 273: void ! 274: ring_consume_data(ring, buffer, count) ! 275: Ring *ring; ! 276: char *buffer; ! 277: int count; ! 278: { ! 279: int i; ! 280: ! 281: while (count) { ! 282: i = MIN(count, ring_full_consecutive(ring)); ! 283: memcpy(buffer, ring->consume, i); ! 284: ring_consumed(ring, i); ! 285: count -= i; ! 286: buffer += i; ! 287: } ! 288: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.