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