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