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