xref: /dpdk/lib/cmdline/cmdline_cirbuf.c (revision 99a2dd955fba6e4cc23b77d590a033650ced9c45)
1*99a2dd95SBruce Richardson /* SPDX-License-Identifier: BSD-3-Clause
2*99a2dd95SBruce Richardson  * Copyright(c) 2010-2014 Intel Corporation.
3*99a2dd95SBruce Richardson  * Copyright (c) 2009, Olivier MATZ <zer0@droids-corp.org>
4*99a2dd95SBruce Richardson  * All rights reserved.
5*99a2dd95SBruce Richardson  */
6*99a2dd95SBruce Richardson 
7*99a2dd95SBruce Richardson #include <string.h>
8*99a2dd95SBruce Richardson #include <errno.h>
9*99a2dd95SBruce Richardson #include <stdio.h>
10*99a2dd95SBruce Richardson 
11*99a2dd95SBruce Richardson #include "cmdline_cirbuf.h"
12*99a2dd95SBruce Richardson 
13*99a2dd95SBruce Richardson 
14*99a2dd95SBruce Richardson int
cirbuf_init(struct cirbuf * cbuf,char * buf,unsigned int start,unsigned int maxlen)15*99a2dd95SBruce Richardson cirbuf_init(struct cirbuf *cbuf, char *buf, unsigned int start, unsigned int maxlen)
16*99a2dd95SBruce Richardson {
17*99a2dd95SBruce Richardson 	if (!cbuf || !buf)
18*99a2dd95SBruce Richardson 		return -EINVAL;
19*99a2dd95SBruce Richardson 	cbuf->maxlen = maxlen;
20*99a2dd95SBruce Richardson 	cbuf->len = 0;
21*99a2dd95SBruce Richardson 	cbuf->start = start;
22*99a2dd95SBruce Richardson 	cbuf->end = start;
23*99a2dd95SBruce Richardson 	cbuf->buf = buf;
24*99a2dd95SBruce Richardson 	return 0;
25*99a2dd95SBruce Richardson }
26*99a2dd95SBruce Richardson 
27*99a2dd95SBruce Richardson /* multiple add */
28*99a2dd95SBruce Richardson 
29*99a2dd95SBruce Richardson int
cirbuf_add_buf_head(struct cirbuf * cbuf,const char * c,unsigned int n)30*99a2dd95SBruce Richardson cirbuf_add_buf_head(struct cirbuf *cbuf, const char *c, unsigned int n)
31*99a2dd95SBruce Richardson {
32*99a2dd95SBruce Richardson 	unsigned int e;
33*99a2dd95SBruce Richardson 
34*99a2dd95SBruce Richardson 	if (!cbuf || !c || !n || n > CIRBUF_GET_FREELEN(cbuf))
35*99a2dd95SBruce Richardson 		return -EINVAL;
36*99a2dd95SBruce Richardson 
37*99a2dd95SBruce Richardson 	e = CIRBUF_IS_EMPTY(cbuf) ? 1 : 0;
38*99a2dd95SBruce Richardson 
39*99a2dd95SBruce Richardson 	if (n < cbuf->start + e) {
40*99a2dd95SBruce Richardson 		dprintf("s[%d] -> d[%d] (%d)\n", 0, cbuf->start - n + e, n);
41*99a2dd95SBruce Richardson 		memcpy(cbuf->buf + cbuf->start - n + e, c, n);
42*99a2dd95SBruce Richardson 	}
43*99a2dd95SBruce Richardson 	else {
44*99a2dd95SBruce Richardson 		dprintf("s[%d] -> d[%d] (%d)\n", + n - (cbuf->start + e), 0,
45*99a2dd95SBruce Richardson 			cbuf->start + e);
46*99a2dd95SBruce Richardson 		dprintf("s[%d] -> d[%d] (%d)\n", cbuf->maxlen - n +
47*99a2dd95SBruce Richardson 			(cbuf->start + e), 0, n - (cbuf->start + e));
48*99a2dd95SBruce Richardson 		memcpy(cbuf->buf, c  + n - (cbuf->start + e) , cbuf->start + e);
49*99a2dd95SBruce Richardson 		memcpy(cbuf->buf + cbuf->maxlen - n + (cbuf->start + e), c,
50*99a2dd95SBruce Richardson 		       n - (cbuf->start + e));
51*99a2dd95SBruce Richardson 	}
52*99a2dd95SBruce Richardson 	cbuf->len += n;
53*99a2dd95SBruce Richardson 	cbuf->start += (cbuf->maxlen - n + e);
54*99a2dd95SBruce Richardson 	cbuf->start %= cbuf->maxlen;
55*99a2dd95SBruce Richardson 	return n;
56*99a2dd95SBruce Richardson }
57*99a2dd95SBruce Richardson 
58*99a2dd95SBruce Richardson /* multiple add */
59*99a2dd95SBruce Richardson 
60*99a2dd95SBruce Richardson int
cirbuf_add_buf_tail(struct cirbuf * cbuf,const char * c,unsigned int n)61*99a2dd95SBruce Richardson cirbuf_add_buf_tail(struct cirbuf *cbuf, const char *c, unsigned int n)
62*99a2dd95SBruce Richardson {
63*99a2dd95SBruce Richardson 	unsigned int e;
64*99a2dd95SBruce Richardson 
65*99a2dd95SBruce Richardson 	if (!cbuf || !c || !n || n > CIRBUF_GET_FREELEN(cbuf))
66*99a2dd95SBruce Richardson 		return -EINVAL;
67*99a2dd95SBruce Richardson 
68*99a2dd95SBruce Richardson 	e = CIRBUF_IS_EMPTY(cbuf) ? 1 : 0;
69*99a2dd95SBruce Richardson 
70*99a2dd95SBruce Richardson 	if (n < cbuf->maxlen - cbuf->end - 1 + e) {
71*99a2dd95SBruce Richardson 		dprintf("s[%d] -> d[%d] (%d)\n", 0, cbuf->end + !e, n);
72*99a2dd95SBruce Richardson 		memcpy(cbuf->buf + cbuf->end + !e, c, n);
73*99a2dd95SBruce Richardson 	}
74*99a2dd95SBruce Richardson 	else {
75*99a2dd95SBruce Richardson 		dprintf("s[%d] -> d[%d] (%d)\n", cbuf->end + !e, 0,
76*99a2dd95SBruce Richardson 			cbuf->maxlen - cbuf->end - 1 + e);
77*99a2dd95SBruce Richardson 		dprintf("s[%d] -> d[%d] (%d)\n", cbuf->maxlen - cbuf->end - 1 +
78*99a2dd95SBruce Richardson 			e, 0, n - cbuf->maxlen + cbuf->end + 1 - e);
79*99a2dd95SBruce Richardson 		memcpy(cbuf->buf + cbuf->end + !e, c, cbuf->maxlen -
80*99a2dd95SBruce Richardson 		       cbuf->end - 1 + e);
81*99a2dd95SBruce Richardson 		memcpy(cbuf->buf, c + cbuf->maxlen - cbuf->end - 1 + e,
82*99a2dd95SBruce Richardson 		       n - cbuf->maxlen + cbuf->end + 1 - e);
83*99a2dd95SBruce Richardson 	}
84*99a2dd95SBruce Richardson 	cbuf->len += n;
85*99a2dd95SBruce Richardson 	cbuf->end += n - e;
86*99a2dd95SBruce Richardson 	cbuf->end %= cbuf->maxlen;
87*99a2dd95SBruce Richardson 	return n;
88*99a2dd95SBruce Richardson }
89*99a2dd95SBruce Richardson 
90*99a2dd95SBruce Richardson /* add at head */
91*99a2dd95SBruce Richardson 
92*99a2dd95SBruce Richardson static inline void
__cirbuf_add_head(struct cirbuf * cbuf,char c)93*99a2dd95SBruce Richardson __cirbuf_add_head(struct cirbuf * cbuf, char c)
94*99a2dd95SBruce Richardson {
95*99a2dd95SBruce Richardson 	if (!CIRBUF_IS_EMPTY(cbuf)) {
96*99a2dd95SBruce Richardson 		cbuf->start += (cbuf->maxlen - 1);
97*99a2dd95SBruce Richardson 		cbuf->start %= cbuf->maxlen;
98*99a2dd95SBruce Richardson 	}
99*99a2dd95SBruce Richardson 	cbuf->buf[cbuf->start] = c;
100*99a2dd95SBruce Richardson 	cbuf->len ++;
101*99a2dd95SBruce Richardson }
102*99a2dd95SBruce Richardson 
103*99a2dd95SBruce Richardson int
cirbuf_add_head_safe(struct cirbuf * cbuf,char c)104*99a2dd95SBruce Richardson cirbuf_add_head_safe(struct cirbuf * cbuf, char c)
105*99a2dd95SBruce Richardson {
106*99a2dd95SBruce Richardson 	if (cbuf && !CIRBUF_IS_FULL(cbuf)) {
107*99a2dd95SBruce Richardson 		__cirbuf_add_head(cbuf, c);
108*99a2dd95SBruce Richardson 		return 0;
109*99a2dd95SBruce Richardson 	}
110*99a2dd95SBruce Richardson 	return -EINVAL;
111*99a2dd95SBruce Richardson }
112*99a2dd95SBruce Richardson 
113*99a2dd95SBruce Richardson void
cirbuf_add_head(struct cirbuf * cbuf,char c)114*99a2dd95SBruce Richardson cirbuf_add_head(struct cirbuf * cbuf, char c)
115*99a2dd95SBruce Richardson {
116*99a2dd95SBruce Richardson 	__cirbuf_add_head(cbuf, c);
117*99a2dd95SBruce Richardson }
118*99a2dd95SBruce Richardson 
119*99a2dd95SBruce Richardson /* add at tail */
120*99a2dd95SBruce Richardson 
121*99a2dd95SBruce Richardson static inline void
__cirbuf_add_tail(struct cirbuf * cbuf,char c)122*99a2dd95SBruce Richardson __cirbuf_add_tail(struct cirbuf * cbuf, char c)
123*99a2dd95SBruce Richardson {
124*99a2dd95SBruce Richardson 	if (!CIRBUF_IS_EMPTY(cbuf)) {
125*99a2dd95SBruce Richardson 		cbuf->end ++;
126*99a2dd95SBruce Richardson 		cbuf->end %= cbuf->maxlen;
127*99a2dd95SBruce Richardson 	}
128*99a2dd95SBruce Richardson 	cbuf->buf[cbuf->end] = c;
129*99a2dd95SBruce Richardson 	cbuf->len ++;
130*99a2dd95SBruce Richardson }
131*99a2dd95SBruce Richardson 
132*99a2dd95SBruce Richardson int
cirbuf_add_tail_safe(struct cirbuf * cbuf,char c)133*99a2dd95SBruce Richardson cirbuf_add_tail_safe(struct cirbuf * cbuf, char c)
134*99a2dd95SBruce Richardson {
135*99a2dd95SBruce Richardson 	if (cbuf && !CIRBUF_IS_FULL(cbuf)) {
136*99a2dd95SBruce Richardson 		__cirbuf_add_tail(cbuf, c);
137*99a2dd95SBruce Richardson 		return 0;
138*99a2dd95SBruce Richardson 	}
139*99a2dd95SBruce Richardson 	return -EINVAL;
140*99a2dd95SBruce Richardson }
141*99a2dd95SBruce Richardson 
142*99a2dd95SBruce Richardson void
cirbuf_add_tail(struct cirbuf * cbuf,char c)143*99a2dd95SBruce Richardson cirbuf_add_tail(struct cirbuf * cbuf, char c)
144*99a2dd95SBruce Richardson {
145*99a2dd95SBruce Richardson 	__cirbuf_add_tail(cbuf, c);
146*99a2dd95SBruce Richardson }
147*99a2dd95SBruce Richardson 
148*99a2dd95SBruce Richardson 
149*99a2dd95SBruce Richardson static inline void
__cirbuf_shift_left(struct cirbuf * cbuf)150*99a2dd95SBruce Richardson __cirbuf_shift_left(struct cirbuf *cbuf)
151*99a2dd95SBruce Richardson {
152*99a2dd95SBruce Richardson 	unsigned int i;
153*99a2dd95SBruce Richardson 	char tmp = cbuf->buf[cbuf->start];
154*99a2dd95SBruce Richardson 
155*99a2dd95SBruce Richardson 	for (i=0 ; i<cbuf->len ; i++) {
156*99a2dd95SBruce Richardson 		cbuf->buf[(cbuf->start+i)%cbuf->maxlen] =
157*99a2dd95SBruce Richardson 			cbuf->buf[(cbuf->start+i+1)%cbuf->maxlen];
158*99a2dd95SBruce Richardson 	}
159*99a2dd95SBruce Richardson 	cbuf->buf[(cbuf->start-1+cbuf->maxlen)%cbuf->maxlen] = tmp;
160*99a2dd95SBruce Richardson 	cbuf->start += (cbuf->maxlen - 1);
161*99a2dd95SBruce Richardson 	cbuf->start %= cbuf->maxlen;
162*99a2dd95SBruce Richardson 	cbuf->end += (cbuf->maxlen - 1);
163*99a2dd95SBruce Richardson 	cbuf->end %= cbuf->maxlen;
164*99a2dd95SBruce Richardson }
165*99a2dd95SBruce Richardson 
166*99a2dd95SBruce Richardson static inline void
__cirbuf_shift_right(struct cirbuf * cbuf)167*99a2dd95SBruce Richardson __cirbuf_shift_right(struct cirbuf *cbuf)
168*99a2dd95SBruce Richardson {
169*99a2dd95SBruce Richardson 	unsigned int i;
170*99a2dd95SBruce Richardson 	char tmp = cbuf->buf[cbuf->end];
171*99a2dd95SBruce Richardson 
172*99a2dd95SBruce Richardson 	for (i=0 ; i<cbuf->len ; i++) {
173*99a2dd95SBruce Richardson 		cbuf->buf[(cbuf->end+cbuf->maxlen-i)%cbuf->maxlen] =
174*99a2dd95SBruce Richardson 			cbuf->buf[(cbuf->end+cbuf->maxlen-i-1)%cbuf->maxlen];
175*99a2dd95SBruce Richardson 	}
176*99a2dd95SBruce Richardson 	cbuf->buf[(cbuf->end+1)%cbuf->maxlen] = tmp;
177*99a2dd95SBruce Richardson 	cbuf->start += 1;
178*99a2dd95SBruce Richardson 	cbuf->start %= cbuf->maxlen;
179*99a2dd95SBruce Richardson 	cbuf->end += 1;
180*99a2dd95SBruce Richardson 	cbuf->end %= cbuf->maxlen;
181*99a2dd95SBruce Richardson }
182*99a2dd95SBruce Richardson 
183*99a2dd95SBruce Richardson /* XXX we could do a better algorithm here... */
184*99a2dd95SBruce Richardson int
cirbuf_align_left(struct cirbuf * cbuf)185*99a2dd95SBruce Richardson cirbuf_align_left(struct cirbuf * cbuf)
186*99a2dd95SBruce Richardson {
187*99a2dd95SBruce Richardson 	if (!cbuf)
188*99a2dd95SBruce Richardson 		return -EINVAL;
189*99a2dd95SBruce Richardson 
190*99a2dd95SBruce Richardson 	if (cbuf->start < cbuf->maxlen/2) {
191*99a2dd95SBruce Richardson 		while (cbuf->start != 0) {
192*99a2dd95SBruce Richardson 			__cirbuf_shift_left(cbuf);
193*99a2dd95SBruce Richardson 		}
194*99a2dd95SBruce Richardson 	}
195*99a2dd95SBruce Richardson 	else {
196*99a2dd95SBruce Richardson 		while (cbuf->start != 0) {
197*99a2dd95SBruce Richardson 			__cirbuf_shift_right(cbuf);
198*99a2dd95SBruce Richardson 		}
199*99a2dd95SBruce Richardson 	}
200*99a2dd95SBruce Richardson 
201*99a2dd95SBruce Richardson 	return 0;
202*99a2dd95SBruce Richardson }
203*99a2dd95SBruce Richardson 
204*99a2dd95SBruce Richardson /* XXX we could do a better algorithm here... */
205*99a2dd95SBruce Richardson int
cirbuf_align_right(struct cirbuf * cbuf)206*99a2dd95SBruce Richardson cirbuf_align_right(struct cirbuf * cbuf)
207*99a2dd95SBruce Richardson {
208*99a2dd95SBruce Richardson 	if (!cbuf)
209*99a2dd95SBruce Richardson 		return -EINVAL;
210*99a2dd95SBruce Richardson 
211*99a2dd95SBruce Richardson 	if (cbuf->start >= cbuf->maxlen/2) {
212*99a2dd95SBruce Richardson 		while (cbuf->end != cbuf->maxlen-1) {
213*99a2dd95SBruce Richardson 			__cirbuf_shift_left(cbuf);
214*99a2dd95SBruce Richardson 		}
215*99a2dd95SBruce Richardson 	}
216*99a2dd95SBruce Richardson 	else {
217*99a2dd95SBruce Richardson 		while (cbuf->start != cbuf->maxlen-1) {
218*99a2dd95SBruce Richardson 			__cirbuf_shift_right(cbuf);
219*99a2dd95SBruce Richardson 		}
220*99a2dd95SBruce Richardson 	}
221*99a2dd95SBruce Richardson 
222*99a2dd95SBruce Richardson 	return 0;
223*99a2dd95SBruce Richardson }
224*99a2dd95SBruce Richardson 
225*99a2dd95SBruce Richardson /* buffer del */
226*99a2dd95SBruce Richardson 
227*99a2dd95SBruce Richardson int
cirbuf_del_buf_head(struct cirbuf * cbuf,unsigned int size)228*99a2dd95SBruce Richardson cirbuf_del_buf_head(struct cirbuf *cbuf, unsigned int size)
229*99a2dd95SBruce Richardson {
230*99a2dd95SBruce Richardson 	if (!cbuf || !size || size > CIRBUF_GET_LEN(cbuf))
231*99a2dd95SBruce Richardson 		return -EINVAL;
232*99a2dd95SBruce Richardson 
233*99a2dd95SBruce Richardson 	cbuf->len -= size;
234*99a2dd95SBruce Richardson 	if (CIRBUF_IS_EMPTY(cbuf)) {
235*99a2dd95SBruce Richardson 		cbuf->start += size - 1;
236*99a2dd95SBruce Richardson 		cbuf->start %= cbuf->maxlen;
237*99a2dd95SBruce Richardson 	}
238*99a2dd95SBruce Richardson 	else {
239*99a2dd95SBruce Richardson 		cbuf->start += size;
240*99a2dd95SBruce Richardson 		cbuf->start %= cbuf->maxlen;
241*99a2dd95SBruce Richardson 	}
242*99a2dd95SBruce Richardson 	return 0;
243*99a2dd95SBruce Richardson }
244*99a2dd95SBruce Richardson 
245*99a2dd95SBruce Richardson /* buffer del */
246*99a2dd95SBruce Richardson 
247*99a2dd95SBruce Richardson int
cirbuf_del_buf_tail(struct cirbuf * cbuf,unsigned int size)248*99a2dd95SBruce Richardson cirbuf_del_buf_tail(struct cirbuf *cbuf, unsigned int size)
249*99a2dd95SBruce Richardson {
250*99a2dd95SBruce Richardson 	if (!cbuf || !size || size > CIRBUF_GET_LEN(cbuf))
251*99a2dd95SBruce Richardson 		return -EINVAL;
252*99a2dd95SBruce Richardson 
253*99a2dd95SBruce Richardson 	cbuf->len -= size;
254*99a2dd95SBruce Richardson 	if (CIRBUF_IS_EMPTY(cbuf)) {
255*99a2dd95SBruce Richardson 		cbuf->end  += (cbuf->maxlen - size + 1);
256*99a2dd95SBruce Richardson 		cbuf->end %= cbuf->maxlen;
257*99a2dd95SBruce Richardson 	}
258*99a2dd95SBruce Richardson 	else {
259*99a2dd95SBruce Richardson 		cbuf->end  += (cbuf->maxlen - size);
260*99a2dd95SBruce Richardson 		cbuf->end %= cbuf->maxlen;
261*99a2dd95SBruce Richardson 	}
262*99a2dd95SBruce Richardson 	return 0;
263*99a2dd95SBruce Richardson }
264*99a2dd95SBruce Richardson 
265*99a2dd95SBruce Richardson /* del at head */
266*99a2dd95SBruce Richardson 
267*99a2dd95SBruce Richardson static inline void
__cirbuf_del_head(struct cirbuf * cbuf)268*99a2dd95SBruce Richardson __cirbuf_del_head(struct cirbuf * cbuf)
269*99a2dd95SBruce Richardson {
270*99a2dd95SBruce Richardson 	cbuf->len --;
271*99a2dd95SBruce Richardson 	if (!CIRBUF_IS_EMPTY(cbuf)) {
272*99a2dd95SBruce Richardson 		cbuf->start ++;
273*99a2dd95SBruce Richardson 		cbuf->start %= cbuf->maxlen;
274*99a2dd95SBruce Richardson 	}
275*99a2dd95SBruce Richardson }
276*99a2dd95SBruce Richardson 
277*99a2dd95SBruce Richardson int
cirbuf_del_head_safe(struct cirbuf * cbuf)278*99a2dd95SBruce Richardson cirbuf_del_head_safe(struct cirbuf * cbuf)
279*99a2dd95SBruce Richardson {
280*99a2dd95SBruce Richardson 	if (cbuf && !CIRBUF_IS_EMPTY(cbuf)) {
281*99a2dd95SBruce Richardson 		__cirbuf_del_head(cbuf);
282*99a2dd95SBruce Richardson 		return 0;
283*99a2dd95SBruce Richardson 	}
284*99a2dd95SBruce Richardson 	return -EINVAL;
285*99a2dd95SBruce Richardson }
286*99a2dd95SBruce Richardson 
287*99a2dd95SBruce Richardson void
cirbuf_del_head(struct cirbuf * cbuf)288*99a2dd95SBruce Richardson cirbuf_del_head(struct cirbuf * cbuf)
289*99a2dd95SBruce Richardson {
290*99a2dd95SBruce Richardson 	__cirbuf_del_head(cbuf);
291*99a2dd95SBruce Richardson }
292*99a2dd95SBruce Richardson 
293*99a2dd95SBruce Richardson /* del at tail */
294*99a2dd95SBruce Richardson 
295*99a2dd95SBruce Richardson static inline void
__cirbuf_del_tail(struct cirbuf * cbuf)296*99a2dd95SBruce Richardson __cirbuf_del_tail(struct cirbuf * cbuf)
297*99a2dd95SBruce Richardson {
298*99a2dd95SBruce Richardson 	cbuf->len --;
299*99a2dd95SBruce Richardson 	if (!CIRBUF_IS_EMPTY(cbuf)) {
300*99a2dd95SBruce Richardson 		cbuf->end  += (cbuf->maxlen - 1);
301*99a2dd95SBruce Richardson 		cbuf->end %= cbuf->maxlen;
302*99a2dd95SBruce Richardson 	}
303*99a2dd95SBruce Richardson }
304*99a2dd95SBruce Richardson 
305*99a2dd95SBruce Richardson int
cirbuf_del_tail_safe(struct cirbuf * cbuf)306*99a2dd95SBruce Richardson cirbuf_del_tail_safe(struct cirbuf * cbuf)
307*99a2dd95SBruce Richardson {
308*99a2dd95SBruce Richardson 	if (cbuf && !CIRBUF_IS_EMPTY(cbuf)) {
309*99a2dd95SBruce Richardson 		__cirbuf_del_tail(cbuf);
310*99a2dd95SBruce Richardson 		return 0;
311*99a2dd95SBruce Richardson 	}
312*99a2dd95SBruce Richardson 	return -EINVAL;
313*99a2dd95SBruce Richardson }
314*99a2dd95SBruce Richardson 
315*99a2dd95SBruce Richardson void
cirbuf_del_tail(struct cirbuf * cbuf)316*99a2dd95SBruce Richardson cirbuf_del_tail(struct cirbuf * cbuf)
317*99a2dd95SBruce Richardson {
318*99a2dd95SBruce Richardson 	__cirbuf_del_tail(cbuf);
319*99a2dd95SBruce Richardson }
320*99a2dd95SBruce Richardson 
321*99a2dd95SBruce Richardson /* convert to buffer */
322*99a2dd95SBruce Richardson 
323*99a2dd95SBruce Richardson int
cirbuf_get_buf_head(struct cirbuf * cbuf,char * c,unsigned int size)324*99a2dd95SBruce Richardson cirbuf_get_buf_head(struct cirbuf *cbuf, char *c, unsigned int size)
325*99a2dd95SBruce Richardson {
326*99a2dd95SBruce Richardson 	unsigned int n;
327*99a2dd95SBruce Richardson 
328*99a2dd95SBruce Richardson 	if (!cbuf || !c)
329*99a2dd95SBruce Richardson 		return -EINVAL;
330*99a2dd95SBruce Richardson 
331*99a2dd95SBruce Richardson 	n = (size < CIRBUF_GET_LEN(cbuf)) ? size : CIRBUF_GET_LEN(cbuf);
332*99a2dd95SBruce Richardson 
333*99a2dd95SBruce Richardson 	if (!n)
334*99a2dd95SBruce Richardson 		return 0;
335*99a2dd95SBruce Richardson 
336*99a2dd95SBruce Richardson 	if (cbuf->start <= cbuf->end) {
337*99a2dd95SBruce Richardson 		dprintf("s[%d] -> d[%d] (%d)\n", cbuf->start, 0, n);
338*99a2dd95SBruce Richardson 		memcpy(c, cbuf->buf + cbuf->start , n);
339*99a2dd95SBruce Richardson 	}
340*99a2dd95SBruce Richardson 	else {
341*99a2dd95SBruce Richardson 		/* check if we need to go from end to the beginning */
342*99a2dd95SBruce Richardson 		if (n <= cbuf->maxlen - cbuf->start) {
343*99a2dd95SBruce Richardson 			dprintf("s[%d] -> d[%d] (%d)\n", 0, cbuf->start, n);
344*99a2dd95SBruce Richardson 			memcpy(c, cbuf->buf + cbuf->start , n);
345*99a2dd95SBruce Richardson 		}
346*99a2dd95SBruce Richardson 		else {
347*99a2dd95SBruce Richardson 			dprintf("s[%d] -> d[%d] (%d)\n", cbuf->start, 0,
348*99a2dd95SBruce Richardson 				cbuf->maxlen - cbuf->start);
349*99a2dd95SBruce Richardson 			dprintf("s[%d] -> d[%d] (%d)\n", 0, cbuf->maxlen - cbuf->start,
350*99a2dd95SBruce Richardson 				n - cbuf->maxlen + cbuf->start);
351*99a2dd95SBruce Richardson 			memcpy(c, cbuf->buf + cbuf->start , cbuf->maxlen - cbuf->start);
352*99a2dd95SBruce Richardson 			memcpy(c + cbuf->maxlen - cbuf->start, cbuf->buf,
353*99a2dd95SBruce Richardson 				   n - cbuf->maxlen + cbuf->start);
354*99a2dd95SBruce Richardson 		}
355*99a2dd95SBruce Richardson 	}
356*99a2dd95SBruce Richardson 	return n;
357*99a2dd95SBruce Richardson }
358*99a2dd95SBruce Richardson 
359*99a2dd95SBruce Richardson /* convert to buffer */
360*99a2dd95SBruce Richardson 
361*99a2dd95SBruce Richardson int
cirbuf_get_buf_tail(struct cirbuf * cbuf,char * c,unsigned int size)362*99a2dd95SBruce Richardson cirbuf_get_buf_tail(struct cirbuf *cbuf, char *c, unsigned int size)
363*99a2dd95SBruce Richardson {
364*99a2dd95SBruce Richardson 	unsigned int n;
365*99a2dd95SBruce Richardson 
366*99a2dd95SBruce Richardson 	if (!cbuf || !c)
367*99a2dd95SBruce Richardson 		return -EINVAL;
368*99a2dd95SBruce Richardson 
369*99a2dd95SBruce Richardson 	n = (size < CIRBUF_GET_LEN(cbuf)) ? size : CIRBUF_GET_LEN(cbuf);
370*99a2dd95SBruce Richardson 
371*99a2dd95SBruce Richardson 	if (!n)
372*99a2dd95SBruce Richardson 		return 0;
373*99a2dd95SBruce Richardson 
374*99a2dd95SBruce Richardson 	if (cbuf->start <= cbuf->end) {
375*99a2dd95SBruce Richardson 		dprintf("s[%d] -> d[%d] (%d)\n", cbuf->end - n + 1, 0, n);
376*99a2dd95SBruce Richardson 		memcpy(c, cbuf->buf + cbuf->end - n + 1, n);
377*99a2dd95SBruce Richardson 	}
378*99a2dd95SBruce Richardson 	else {
379*99a2dd95SBruce Richardson 		/* check if we need to go from end to the beginning */
380*99a2dd95SBruce Richardson 		if (n <= cbuf->end + 1) {
381*99a2dd95SBruce Richardson 			dprintf("s[%d] -> d[%d] (%d)\n", 0, cbuf->end - n + 1, n);
382*99a2dd95SBruce Richardson 			memcpy(c, cbuf->buf + cbuf->end - n + 1, n);
383*99a2dd95SBruce Richardson 		}
384*99a2dd95SBruce Richardson 		else {
385*99a2dd95SBruce Richardson 			dprintf("s[%d] -> d[%d] (%d)\n", 0,
386*99a2dd95SBruce Richardson 				cbuf->maxlen - cbuf->start, cbuf->end + 1);
387*99a2dd95SBruce Richardson 			dprintf("s[%d] -> d[%d] (%d)\n",
388*99a2dd95SBruce Richardson 				cbuf->maxlen - n + cbuf->end + 1, 0, n - cbuf->end - 1);
389*99a2dd95SBruce Richardson 			memcpy(c + cbuf->maxlen - cbuf->start,
390*99a2dd95SBruce Richardson 					       cbuf->buf, cbuf->end + 1);
391*99a2dd95SBruce Richardson 			memcpy(c, cbuf->buf + cbuf->maxlen - n + cbuf->end +1,
392*99a2dd95SBruce Richardson 				   n - cbuf->end - 1);
393*99a2dd95SBruce Richardson 		}
394*99a2dd95SBruce Richardson 	}
395*99a2dd95SBruce Richardson 	return n;
396*99a2dd95SBruce Richardson }
397*99a2dd95SBruce Richardson 
398*99a2dd95SBruce Richardson /* get head or get tail */
399*99a2dd95SBruce Richardson 
400*99a2dd95SBruce Richardson char
cirbuf_get_head(struct cirbuf * cbuf)401*99a2dd95SBruce Richardson cirbuf_get_head(struct cirbuf * cbuf)
402*99a2dd95SBruce Richardson {
403*99a2dd95SBruce Richardson 	return cbuf->buf[cbuf->start];
404*99a2dd95SBruce Richardson }
405*99a2dd95SBruce Richardson 
406*99a2dd95SBruce Richardson /* get head or get tail */
407*99a2dd95SBruce Richardson 
408*99a2dd95SBruce Richardson char
cirbuf_get_tail(struct cirbuf * cbuf)409*99a2dd95SBruce Richardson cirbuf_get_tail(struct cirbuf * cbuf)
410*99a2dd95SBruce Richardson {
411*99a2dd95SBruce Richardson 	return cbuf->buf[cbuf->end];
412*99a2dd95SBruce Richardson }
413