dpdk/lib/cmdline/cmdline_cirbuf.c
<<
>>
Prefs
   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
  14int
  15cirbuf_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
  29int
  30cirbuf_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
  60int
  61cirbuf_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
  92static 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
 103int
 104cirbuf_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
 113void
 114cirbuf_add_head(struct cirbuf * cbuf, char c)
 115{
 116        __cirbuf_add_head(cbuf, c);
 117}
 118
 119/* add at tail */
 120
 121static 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
 132int
 133cirbuf_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
 142void
 143cirbuf_add_tail(struct cirbuf * cbuf, char c)
 144{
 145        __cirbuf_add_tail(cbuf, c);
 146}
 147
 148
 149static 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
 166static 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... */
 184int
 185cirbuf_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... */
 205int
 206cirbuf_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
 227int
 228cirbuf_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
 247int
 248cirbuf_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
 267static 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
 277int
 278cirbuf_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
 287void
 288cirbuf_del_head(struct cirbuf * cbuf)
 289{
 290        __cirbuf_del_head(cbuf);
 291}
 292
 293/* del at tail */
 294
 295static 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
 305int
 306cirbuf_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
 315void
 316cirbuf_del_tail(struct cirbuf * cbuf)
 317{
 318        __cirbuf_del_tail(cbuf);
 319}
 320
 321/* convert to buffer */
 322
 323int
 324cirbuf_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
 361int
 362cirbuf_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
 400char
 401cirbuf_get_head(struct cirbuf * cbuf)
 402{
 403        return cbuf->buf[cbuf->start];
 404}
 405
 406/* get head or get tail */
 407
 408char
 409cirbuf_get_tail(struct cirbuf * cbuf)
 410{
 411        return cbuf->buf[cbuf->end];
 412}
 413