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