first public release
[dpdk.git] / lib / librte_cmdline / cmdline_cirbuf.c
1 /*-
2  *   BSD LICENSE
3  * 
4  *   Copyright(c) 2010-2012 Intel Corporation. All rights reserved.
5  *   All rights reserved.
6  * 
7  *   Redistribution and use in source and binary forms, with or without 
8  *   modification, are permitted provided that the following conditions 
9  *   are met:
10  * 
11  *     * Redistributions of source code must retain the above copyright 
12  *       notice, this list of conditions and the following disclaimer.
13  *     * Redistributions in binary form must reproduce the above copyright 
14  *       notice, this list of conditions and the following disclaimer in 
15  *       the documentation and/or other materials provided with the 
16  *       distribution.
17  *     * Neither the name of Intel Corporation nor the names of its 
18  *       contributors may be used to endorse or promote products derived 
19  *       from this software without specific prior written permission.
20  * 
21  *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
22  *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
23  *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 
24  *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
25  *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
26  *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
27  *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 
28  *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 
29  *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
30  *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
31  *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32  * 
33  *  version: DPDK.L.1.2.3-3
34  */
35
36 /*
37  * Copyright (c) 2009, Olivier MATZ <zer0@droids-corp.org>
38  * All rights reserved.
39  * Redistribution and use in source and binary forms, with or without
40  * modification, are permitted provided that the following conditions are met:
41  *
42  *     * Redistributions of source code must retain the above copyright
43  *       notice, this list of conditions and the following disclaimer.
44  *     * Redistributions in binary form must reproduce the above copyright
45  *       notice, this list of conditions and the following disclaimer in the
46  *       documentation and/or other materials provided with the distribution.
47  *     * Neither the name of the University of California, Berkeley nor the
48  *       names of its contributors may be used to endorse or promote products
49  *       derived from this software without specific prior written permission.
50  *
51  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY
52  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
53  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
54  * DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY
55  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
56  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
57  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
58  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
59  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
60  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
61  */
62
63 #include <string.h>
64 #include <errno.h>
65
66 #include "cmdline_cirbuf.h"
67
68
69 void
70 cirbuf_init(struct cirbuf *cbuf, char *buf, unsigned int start, unsigned int maxlen)
71 {
72         cbuf->maxlen = maxlen;
73         cbuf->len = 0;
74         cbuf->start = start;
75         cbuf->end = start;
76         cbuf->buf = buf;
77 }
78
79 /* multiple add */
80
81 int
82 cirbuf_add_buf_head(struct cirbuf *cbuf, const char *c, unsigned int n)
83 {
84         unsigned int e;
85
86         if (!n || n > CIRBUF_GET_FREELEN(cbuf))
87                 return -EINVAL;
88
89         e = CIRBUF_IS_EMPTY(cbuf) ? 1 : 0;
90
91         if (n < cbuf->start + e) {
92                 dprintf("s[%d] -> d[%d] (%d)\n", 0, cbuf->start - n + e, n);
93                 memcpy(cbuf->buf + cbuf->start - n + e, c, n);
94         }
95         else {
96                 dprintf("s[%d] -> d[%d] (%d)\n", + n - (cbuf->start + e), 0,
97                         cbuf->start + e);
98                 dprintf("s[%d] -> d[%d] (%d)\n", cbuf->maxlen - n +
99                         (cbuf->start + e), 0, n - (cbuf->start + e));
100                 memcpy(cbuf->buf, c  + n - (cbuf->start + e) , cbuf->start + e);
101                 memcpy(cbuf->buf + cbuf->maxlen - n + (cbuf->start + e), c,
102                        n - (cbuf->start + e));
103         }
104         cbuf->len += n;
105         cbuf->start += (cbuf->maxlen - n + e);
106         cbuf->start %= cbuf->maxlen;
107         return n;
108 }
109
110 /* multiple add */
111
112 int
113 cirbuf_add_buf_tail(struct cirbuf *cbuf, const char *c, unsigned int n)
114 {
115         unsigned int e;
116
117         if (!n || n > CIRBUF_GET_FREELEN(cbuf))
118                 return -EINVAL;
119
120         e = CIRBUF_IS_EMPTY(cbuf) ? 1 : 0;
121
122         if (n < cbuf->maxlen - cbuf->end - 1 + e) {
123                 dprintf("s[%d] -> d[%d] (%d)\n", 0, cbuf->end + !e, n);
124                 memcpy(cbuf->buf + cbuf->end + !e, c, n);
125         }
126         else {
127                 dprintf("s[%d] -> d[%d] (%d)\n", cbuf->end + !e, 0,
128                         cbuf->maxlen - cbuf->end - 1 + e);
129                 dprintf("s[%d] -> d[%d] (%d)\n", cbuf->maxlen - cbuf->end - 1 +
130                         e, 0, n - cbuf->maxlen + cbuf->end + 1 - e);
131                 memcpy(cbuf->buf + cbuf->end + !e, c, cbuf->maxlen -
132                        cbuf->end - 1 + e);
133                 memcpy(cbuf->buf, c + cbuf->maxlen - cbuf->end - 1 + e,
134                        n - cbuf->maxlen + cbuf->end + 1 - e);
135         }
136         cbuf->len += n;
137         cbuf->end += n - e;
138         cbuf->end %= cbuf->maxlen;
139         return n;
140 }
141
142 /* add at head */
143
144 static inline void
145 __cirbuf_add_head(struct cirbuf * cbuf, char c)
146 {
147         if (!CIRBUF_IS_EMPTY(cbuf)) {
148                 cbuf->start += (cbuf->maxlen - 1);
149                 cbuf->start %= cbuf->maxlen;
150         }
151         cbuf->buf[cbuf->start] = c;
152         cbuf->len ++;
153 }
154
155 int
156 cirbuf_add_head_safe(struct cirbuf * cbuf, char c)
157 {
158         if (cbuf && !CIRBUF_IS_FULL(cbuf)) {
159                 __cirbuf_add_head(cbuf, c);
160                 return 0;
161         }
162         return -EINVAL;
163 }
164
165 void
166 cirbuf_add_head(struct cirbuf * cbuf, char c)
167 {
168         __cirbuf_add_head(cbuf, c);
169 }
170
171 /* add at tail */
172
173 static inline void
174 __cirbuf_add_tail(struct cirbuf * cbuf, char c)
175 {
176         if (!CIRBUF_IS_EMPTY(cbuf)) {
177                 cbuf->end ++;
178                 cbuf->end %= cbuf->maxlen;
179         }
180         cbuf->buf[cbuf->end] = c;
181         cbuf->len ++;
182 }
183
184 int
185 cirbuf_add_tail_safe(struct cirbuf * cbuf, char c)
186 {
187         if (cbuf && !CIRBUF_IS_FULL(cbuf)) {
188                 __cirbuf_add_tail(cbuf, c);
189                 return 0;
190         }
191         return -EINVAL;
192 }
193
194 void
195 cirbuf_add_tail(struct cirbuf * cbuf, char c)
196 {
197         __cirbuf_add_tail(cbuf, c);
198 }
199
200
201 static inline void
202 __cirbuf_shift_left(struct cirbuf *cbuf)
203 {
204         unsigned int i;
205         char tmp = cbuf->buf[cbuf->start];
206
207         for (i=0 ; i<cbuf->len ; i++) {
208                 cbuf->buf[(cbuf->start+i)%cbuf->maxlen] =
209                         cbuf->buf[(cbuf->start+i+1)%cbuf->maxlen];
210         }
211         cbuf->buf[(cbuf->start-1+cbuf->maxlen)%cbuf->maxlen] = tmp;
212         cbuf->start += (cbuf->maxlen - 1);
213         cbuf->start %= cbuf->maxlen;
214         cbuf->end += (cbuf->maxlen - 1);
215         cbuf->end %= cbuf->maxlen;
216 }
217
218 static inline void
219 __cirbuf_shift_right(struct cirbuf *cbuf)
220 {
221         unsigned int i;
222         char tmp = cbuf->buf[cbuf->end];
223
224         for (i=0 ; i<cbuf->len ; i++) {
225                 cbuf->buf[(cbuf->end+cbuf->maxlen-i)%cbuf->maxlen] =
226                         cbuf->buf[(cbuf->end+cbuf->maxlen-i-1)%cbuf->maxlen];
227         }
228         cbuf->buf[(cbuf->end+1)%cbuf->maxlen] = tmp;
229         cbuf->start += 1;
230         cbuf->start %= cbuf->maxlen;
231         cbuf->end += 1;
232         cbuf->end %= cbuf->maxlen;
233 }
234
235 /* XXX we could do a better algorithm here... */
236 void cirbuf_align_left(struct cirbuf * cbuf)
237 {
238         if (cbuf->start < cbuf->maxlen/2) {
239                 while (cbuf->start != 0) {
240                         __cirbuf_shift_left(cbuf);
241                 }
242         }
243         else {
244                 while (cbuf->start != 0) {
245                         __cirbuf_shift_right(cbuf);
246                 }
247         }
248 }
249
250 /* XXX we could do a better algorithm here... */
251 void cirbuf_align_right(struct cirbuf * cbuf)
252 {
253         if (cbuf->start >= cbuf->maxlen/2) {
254                 while (cbuf->end != cbuf->maxlen-1) {
255                         __cirbuf_shift_left(cbuf);
256                 }
257         }
258         else {
259                 while (cbuf->start != cbuf->maxlen-1) {
260                         __cirbuf_shift_right(cbuf);
261                 }
262         }
263 }
264
265 /* buffer del */
266
267 int
268 cirbuf_del_buf_head(struct cirbuf *cbuf, unsigned int size)
269 {
270         if (!size || size > CIRBUF_GET_LEN(cbuf))
271                 return -EINVAL;
272
273         cbuf->len -= size;
274         if (CIRBUF_IS_EMPTY(cbuf)) {
275                 cbuf->start += size - 1;
276                 cbuf->start %= cbuf->maxlen;
277         }
278         else {
279                 cbuf->start += size;
280                 cbuf->start %= cbuf->maxlen;
281         }
282         return 0;
283 }
284
285 /* buffer del */
286
287 int
288 cirbuf_del_buf_tail(struct cirbuf *cbuf, unsigned int size)
289 {
290         if (!size || size > CIRBUF_GET_LEN(cbuf))
291                 return -EINVAL;
292
293         cbuf->len -= size;
294         if (CIRBUF_IS_EMPTY(cbuf)) {
295                 cbuf->end  += (cbuf->maxlen - size + 1);
296                 cbuf->end %= cbuf->maxlen;
297         }
298         else {
299                 cbuf->end  += (cbuf->maxlen - size);
300                 cbuf->end %= cbuf->maxlen;
301         }
302         return 0;
303 }
304
305 /* del at head */
306
307 static inline void
308 __cirbuf_del_head(struct cirbuf * cbuf)
309 {
310         cbuf->len --;
311         if (!CIRBUF_IS_EMPTY(cbuf)) {
312                 cbuf->start ++;
313                 cbuf->start %= cbuf->maxlen;
314         }
315 }
316
317 int
318 cirbuf_del_head_safe(struct cirbuf * cbuf)
319 {
320         if (cbuf && !CIRBUF_IS_EMPTY(cbuf)) {
321                 __cirbuf_del_head(cbuf);
322                 return 0;
323         }
324         return -EINVAL;
325 }
326
327 void
328 cirbuf_del_head(struct cirbuf * cbuf)
329 {
330         __cirbuf_del_head(cbuf);
331 }
332
333 /* del at tail */
334
335 static inline void
336 __cirbuf_del_tail(struct cirbuf * cbuf)
337 {
338         cbuf->len --;
339         if (!CIRBUF_IS_EMPTY(cbuf)) {
340                 cbuf->end  += (cbuf->maxlen - 1);
341                 cbuf->end %= cbuf->maxlen;
342         }
343 }
344
345 int
346 cirbuf_del_tail_safe(struct cirbuf * cbuf)
347 {
348         if (cbuf && !CIRBUF_IS_EMPTY(cbuf)) {
349                 __cirbuf_del_tail(cbuf);
350                 return 0;
351         }
352         return -EINVAL;
353 }
354
355 void
356 cirbuf_del_tail(struct cirbuf * cbuf)
357 {
358         __cirbuf_del_tail(cbuf);
359 }
360
361 /* convert to buffer */
362
363 int
364 cirbuf_get_buf_head(struct cirbuf *cbuf, char *c, unsigned int size)
365 {
366         unsigned int n;
367
368         n = (size < CIRBUF_GET_LEN(cbuf)) ? size : CIRBUF_GET_LEN(cbuf);
369
370         if (!n)
371                 return 0;
372
373         if (cbuf->start <= cbuf->end) {
374                 dprintf("s[%d] -> d[%d] (%d)\n", cbuf->start, 0, n);
375                 memcpy(c, cbuf->buf + cbuf->start , n);
376         }
377         else {
378                 dprintf("s[%d] -> d[%d] (%d)\n", cbuf->start, 0,
379                         cbuf->maxlen - cbuf->start);
380                 dprintf("s[%d] -> d[%d] (%d)\n", 0,cbuf->maxlen - cbuf->start,
381                         n - cbuf->maxlen + cbuf->start);
382                 memcpy(c, cbuf->buf + cbuf->start , cbuf->maxlen - cbuf->start);
383                 memcpy(c + cbuf->maxlen - cbuf->start, cbuf->buf,
384                        n - cbuf->maxlen + cbuf->start);
385         }
386         return n;
387 }
388
389 /* convert to buffer */
390
391 int
392 cirbuf_get_buf_tail(struct cirbuf *cbuf, char *c, unsigned int size)
393 {
394         unsigned int n;
395
396         n = (size < CIRBUF_GET_LEN(cbuf)) ? size : CIRBUF_GET_LEN(cbuf);
397
398         if (!n)
399                 return 0;
400
401         if (cbuf->start <= cbuf->end) {
402                 dprintf("s[%d] -> d[%d] (%d)\n", cbuf->end - n + 1, 0, n);
403                 memcpy(c, cbuf->buf + cbuf->end - n + 1, n);
404         }
405         else {
406                 dprintf("s[%d] -> d[%d] (%d)\n", 0,
407                         cbuf->maxlen - cbuf->start, cbuf->end + 1);
408                 dprintf("s[%d] -> d[%d] (%d)\n",
409                         cbuf->maxlen - n + cbuf->end + 1, 0, n - cbuf->end - 1);
410
411                 memcpy(c + cbuf->maxlen - cbuf->start,
412                        cbuf->buf, cbuf->end + 1);
413                 memcpy(c, cbuf->buf + cbuf->maxlen - n + cbuf->end +1,
414                        n - cbuf->end - 1);
415         }
416         return n;
417 }
418
419 /* get head or get tail */
420
421 char
422 cirbuf_get_head(struct cirbuf * cbuf)
423 {
424         return cbuf->buf[cbuf->start];
425 }
426
427 /* get head or get tail */
428
429 char
430 cirbuf_get_tail(struct cirbuf * cbuf)
431 {
432         return cbuf->buf[cbuf->end];
433 }
434