1 /* 2 * RINGBUF - general support for ring buffers 3 * 4 * Author: 5 * Emile van Bergen, emile@evbergen.xs4all.nl 6 * 7 * Permission to redistribute an original or modified version of this program 8 * in source, intermediate or object code form is hereby granted exclusively 9 * under the terms of the GNU General Public License, version 2. Please see the 10 * file COPYING for details, or refer to http://www.gnu.org/copyleft/gpl.html. 11 * 12 * History: 13 * 2000/11/28 - EvB - Created 14 * 2001/01/09 - EvB - Added ring_capacity inline function 15 * - Made the header a little more readable 16 * 2001/07/02 - EvB - Added ring_peekdata 17 * 2001/07/03 - EvB - Added ring_strncmp as a counting function 18 */ 19 20 21 #ifndef __RINGBUF_H 22 #define __RINGBUF_H 1 23 24 25 /* 26 * INCLUDES & DEFINES 27 */ 28 29 30 #include <sys/types.h> /* for ssize_t */ 31 #include <stdarg.h> /* for va_list */ 32 33 34 /* Return status for ring_read and ring_write */ 35 36 #define RING_OK 0 37 #define RING_EOF 1 /* if we read/wrote less than requested */ 38 #define RING_IOERR 2 /* if the operation returned -1 */ 39 #define RING_EAGAIN 4 /* if error but errno was eagain */ 40 41 42 #ifndef __GNUC__ 43 #define __inline__ /* */ 44 #endif 45 46 47 /* 48 * TYPES 49 */ 50 51 52 /* The ring object itself */ 53 54 typedef struct ring { 55 ssize_t size, r, w; 56 char *buf; 57 } RING; 58 59 60 /* Counting function for peeks */ 61 62 typedef ssize_t (*RINGCNTFUNC)(char *s, ssize_t len, ssize_t seen, va_list ap); 63 64 65 /* 66 * PROTOTYPES 67 */ 68 69 70 /* 71 * Creation / deletion 72 */ 73 74 75 RING *ring_new(ssize_t size); 76 void ring_del(RING *r); 77 78 79 /* 80 * Debugging 81 */ 82 83 84 void ring_debug(RING *r); 85 86 87 /* 88 * Getting / putting 89 */ 90 91 92 /* Get data from the ring. Returns number of bytes removed. */ 93 94 ssize_t ring_get(RING *r, void *data, ssize_t len); 95 ssize_t ring_peekdata(RING *r, void *data, ssize_t len); 96 97 /* Add data to the ring. Returns number of bytes added. */ 98 99 ssize_t ring_put(RING *r, void *data, ssize_t len); 100 101 /* Discard data from the ring. Returns number of bytes removed. 102 If maxlen == 0, discards all. */ 103 104 ssize_t ring_discard(RING *r, ssize_t maxlen); 105 106 107 /* 108 * Open file I/O 109 */ 110 111 112 #if 0 113 114 /* Old interface */ 115 116 /* Get data from the ring and write it to an open file. Returns 117 number of bytes written, 0 if no data was available in the ring, 118 or -1 if a write error occured. If min > 0, specifies the minimum 119 amount of data that must be available before trying to write. 120 If max > 0, specifies the maximum amount of data that may be written 121 at once. */ 122 123 ssize_t ring_write(RING *r, int fd, ssize_t min, ssize_t max); 124 125 /* Read data from and open file and add it to the ring. Returns number 126 of bytes added, 0 if no data was read from the file, either due to 127 EOF or lack of buffer space, or -1 if a write error occured. 128 If min > 0, specifies the minimum amount of data that must be available 129 before trying to write. 130 If max > 0, specifies a maximum amount of data to read. */ 131 132 ssize_t ring_read(RING *r, int fd, ssize_t min, ssize_t max); 133 134 #else 135 136 int ring_read(RING *r, int fd, ssize_t *xfered); 137 int ring_write(RING *r, int fd, ssize_t *xfered, ssize_t max); 138 139 #endif 140 141 142 /* 143 * Scanning functions; return the number of characters avaliable that 144 * satisfies a certain condition 145 */ 146 147 148 /* General function */ 149 150 ssize_t ring_count(RING *r, RINGCNTFUNC func, ...); 151 152 /* Counting functions for use with ring_count */ 153 154 ssize_t _ring_cnt_strspn(char *s, ssize_t len, ssize_t seen, va_list ap); 155 ssize_t _ring_cnt_strcspn(char *s, ssize_t len, ssize_t seen, va_list ap); 156 ssize_t _ring_cnt_strncmp(char *s, ssize_t len, ssize_t seen, va_list ap); 157 158 159 /* 160 * VARIOUS INLINED FUNCTIONS 161 */ 162 163 #if 0 164 165 /* Scanning functions built with ring_count and the counting functions */ 166 167 /* strlen, but returns ring_maxget if no end found */ 168 extern __inline__ ssize_t ring_strlen(RING *r) 169 { 170 return ring_count(r, _ring_cnt_strcspn, "\0", 1); 171 } 172 173 /* strspn, but takes a string with length */ 174 extern __inline__ ssize_t ring_strspn(RING *r, char *s, int slen) 175 { 176 return ring_count(r, _ring_cnt_strspn, s, slen); 177 } 178 179 /* strcspn, but takes a string with length */ 180 extern __inline__ ssize_t ring_strcspn(RING *r, char *s, int slen) 181 { 182 return ring_count(r, _ring_cnt_strcspn, s, slen); 183 } 184 185 /* strncmp, but always returns 1 if different, ignores relative position */ 186 extern __inline__ ssize_t ring_strncmp(RING *r, char *s, int slen) 187 { 188 return ring_count(r, _ring_cnt_strncmp, s, slen) != slen; 189 } 190 191 192 /* 193 * Testing functions 194 */ 195 196 197 /* Put is guaranteed to accept the number of bytes returned by maxput */ 198 199 extern __inline__ ssize_t ring_maxput(RING *r) 200 { 201 return ((r->size + (r->r - (r->w + 1))) % r->size); 202 } 203 204 /* Get is guaranteed to give the number of bytes returned by maxget. */ 205 206 extern __inline__ ssize_t ring_maxget(RING *r) 207 { 208 return ((r->size + (r->w - r->r)) % r->size); 209 } 210 211 /* Check if the ring is empty */ 212 213 extern __inline__ int ring_isempty(RING *r) 214 { 215 return (r->r == r->w); 216 } 217 218 /* Check if the ring is full */ 219 220 extern __inline__ int ring_isfull(RING *r) 221 { 222 return ring_maxput(r) == 0; 223 } 224 225 /* Get the full capacity of the ring, which is the size minus the guard byte 226 that makes it possible to distinguish between a full and an empty ring. */ 227 228 extern __inline__ int ring_capacity(RING *r) 229 { 230 return r->size - 1; 231 } 232 233 234 235 /* Peeking function */ 236 237 /* Look at the single character at the specified position in the string of 238 available bytes. If a position beyond the end of that string is specified, 239 -1 is returned. */ 240 241 extern __inline__ int ring_peek(RING *r, ssize_t pos) 242 { 243 if (pos >= 0 && pos < ring_maxget(r)) { 244 return (r->buf[(r->size + r->r + pos) % r->size]) & 0xff; 245 } 246 247 return -1; 248 } 249 250 #endif 251 252 253 /* Derived testing macros */ 254 255 #define ring_strlen(r) ring_count((r), _ring_cnt_strcspn, "\0", 1) 256 257 #define ring_strspn(r, s, slen) ring_count((r), _ring_cnt_strspn, (s), (slen)) 258 #define ring_strcspn(r, s, slen) ring_count((r), _ring_cnt_strcspn, (s), (slen)) 259 260 /* always returns 1 if different - doesn't test bigger or smaller */ 261 262 #define ring_strncmp(r, s, slen) (ring_count((r), _ring_cnt_strncmp, \ 263 (s), (slen)) != (slen)) 264 265 /* Testing; put is guaranteed to accept the number of bytes given 266 by maxput, and get is guaranteed to return the number of bytes given 267 by maxget. These are also available in the header as inlines. */ 268 269 #define ring_maxput(R) (((R)->size + ((R)->r - ((R)->w + 1))) % (R)->size) 270 #define ring_maxget(R) (((R)->size + ((R)->w - (R)->r)) % (R)->size) 271 272 #define ring_isempty(R) ((R)->r == (R)->w) 273 274 #define ring_capacity(R) ((R)->size - 1) 275 276 /* Peeking function: returns the single character at the specified 277 position in the string of available bytes. If a position beyond 278 the end of that string is specified, -1 is returned. This function 279 is also available inline in the header. */ 280 281 #define ring_peek(R, POS) ( \ 282 ((POS) >= 0 && (POS) < ring_maxget((R))) ? \ 283 ((R)->buf[((R)->size + (R)->r + (POS)) % (R)->size]) & 0xff : \ 284 -1) 285 286 #endif /* ndef __RINGBUF_H */ 287 288