1 /* 2 * This defines a structure for a ring buffer. 3 * 4 * The circular buffer has two parts: 5 *((( 6 * full: [consume, supply) 7 * empty: [supply, consume) 8 *]]] 9 * 10 */ 11 12 #include <stdio.h> 13 #include <errno.h> 14 15 #ifdef size_t 16 #undef size_t 17 #endif 18 19 #include <sys/types.h> 20 #include <sys/ioctl.h> 21 #include <sys/socket.h> 22 23 #include "ring.h" 24 #include "general.h" 25 26 /* Internal macros */ 27 28 #if !defined(MIN) 29 #define MIN(a,b) (((a)<(b))? (a):(b)) 30 #endif /* !defined(MIN) */ 31 32 #define ring_subtract(d,a,b) ((((int)(a))-((int)(b)) >= 0)? \ 33 (a)-(b): (((a)-(b))+(d)->size)) 34 35 #define ring_increment(d,a,c) (((a)+(c) < (d)->top)? \ 36 (a)+(c) : (((a)+(c))-(d)->size)) 37 38 39 /* 40 * The following is a clock, used to determine full, empty, etc. 41 * 42 * There is some trickiness here. Since the ring buffers are initialized 43 * to ZERO on allocation, we need to make sure, when interpreting the 44 * clock, that when the times are EQUAL, then the buffer is FULL. 45 */ 46 static u_long ring_clock = 0; 47 48 49 #define ring_empty(d) (((d)->consume == (d)->supply) && \ 50 ((d)->consumetime >= (d)->supplytime)) 51 #define ring_full(d) (((d)->supply == (d)->consume) && \ 52 ((d)->supplytime > (d)->consumetime)) 53 54 55 56 57 58 /* Buffer state transition routines */ 59 60 ring_init(ring, buffer, count) 61 Ring *ring; 62 char *buffer; 63 int count; 64 { 65 memset((char *)ring, 0, sizeof *ring); 66 67 ring->size = count; 68 69 ring->supply = ring->consume = ring->bottom = buffer; 70 71 ring->top = ring->bottom+ring->size; 72 73 return 1; 74 } 75 76 /* 77 * Add characters from current segment to ring buffer. 78 */ 79 void 80 ring_supplied(ring, count) 81 Ring *ring; 82 int count; 83 { 84 ring->supply = ring_increment(ring, ring->supply, count); 85 ring->supplytime = ++ring_clock; 86 } 87 88 /* 89 * We have just consumed "c" bytes. 90 */ 91 void 92 ring_consumed(ring, count) 93 Ring *ring; 94 int count; 95 { 96 if (count == 0) /* don't update anything */ 97 return; 98 99 ring->consume = ring_increment(ring, ring->consume, count); 100 ring->consumetime = ++ring_clock; 101 /* 102 * Try to encourage "ring_empty_consecutive()" to be large. 103 */ 104 if (ring_empty(ring)) { 105 ring->consume = ring->supply = ring->bottom; 106 } 107 } 108 109 110 111 /* Buffer state query routines */ 112 113 114 /* Number of bytes that may be supplied */ 115 int 116 ring_empty_count(ring) 117 Ring *ring; 118 { 119 if (ring_empty(ring)) { /* if empty */ 120 return ring->size; 121 } else { 122 return ring_subtract(ring, ring->consume, ring->supply); 123 } 124 } 125 126 /* number of CONSECUTIVE bytes that may be supplied */ 127 int 128 ring_empty_consecutive(ring) 129 Ring *ring; 130 { 131 if ((ring->consume < ring->supply) || ring_empty(ring)) { 132 /* 133 * if consume is "below" supply, or empty, then 134 * return distance to the top 135 */ 136 return ring_subtract(ring, ring->top, ring->supply); 137 } else { 138 /* 139 * else, return what we may. 140 */ 141 return ring_subtract(ring, ring->consume, ring->supply); 142 } 143 } 144 145 /* number of bytes that are available for consuming */ 146 int 147 ring_full_count(ring) 148 Ring *ring; 149 { 150 if (ring_full(ring)) { 151 return ring->size; /* nothing consumed, but full */ 152 } else { 153 return ring_subtract(ring, ring->supply, ring->consume); 154 } 155 } 156 157 /* number of CONSECUTIVE bytes available for consuming */ 158 int 159 ring_full_consecutive(ring) 160 Ring *ring; 161 { 162 if ((ring->supply < ring->consume) || ring_full(ring)) { 163 return ring_subtract(ring, ring->top, ring->consume); 164 } else { 165 return ring_subtract(ring, ring->supply, ring->consume); 166 } 167 } 168 169 /* 170 * Move data into the "supply" portion of of the ring buffer. 171 */ 172 void 173 ring_supply_data(ring, buffer, count) 174 Ring *ring; 175 char *buffer; 176 int count; 177 { 178 int i; 179 180 while (count) { 181 i = MIN(count, ring_empty_consecutive(ring)); 182 memcpy(ring->supply, buffer, i); 183 ring_supplied(ring, i); 184 count -= i; 185 buffer += i; 186 } 187 } 188 189 190 /* 191 * Move data from the "consume" portion of the ring buffer 192 */ 193 void 194 ring_consume_data(ring, buffer, count) 195 Ring *ring; 196 char *buffer; 197 int count; 198 { 199 int i; 200 201 while (count) { 202 i = MIN(count, ring_full_consecutive(ring)); 203 memcpy(buffer, ring->consume, i); 204 ring_consumed(ring, i); 205 count -= i; 206 buffer += i; 207 } 208 } 209 210 /* Mark routines */ 211 212 /* XXX do something here */ 213 void 214 ring_mark(ring) 215 Ring *ring; 216 { 217 } 218 219 int 220 ring_at_mark(ring) 221 Ring *ring; 222 { 223 return 0; 224 } 225 226 void 227 ring_clear_mark(ring) 228 Ring *ring; 229 { 230 } 231