Home | History | Annotate | Download | only in src
      1 /******************************************************************************
      2  *
      3  *  Copyright (C) 2015 Google Inc.
      4  *
      5  *  Licensed under the Apache License, Version 2.0 (the "License");
      6  *  you may not use this file except in compliance with the License.
      7  *  You may obtain a copy of the License at:
      8  *
      9  *  http://www.apache.org/licenses/LICENSE-2.0
     10  *
     11  *  Unless required by applicable law or agreed to in writing, software
     12  *  distributed under the License is distributed on an "AS IS" BASIS,
     13  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     14  *  See the License for the specific language governing permissions and
     15  *  limitations under the License.
     16  *
     17  ******************************************************************************/
     18 
     19 #include <assert.h>
     20 #include <stdlib.h>
     21 
     22 #include "osi/include/allocator.h"
     23 #include "osi/include/ringbuffer.h"
     24 
     25 struct ringbuffer_t {
     26   size_t total;
     27   size_t available;
     28   uint8_t *base;
     29   uint8_t *head;
     30   uint8_t *tail;
     31 };
     32 
     33 ringbuffer_t* ringbuffer_init(const size_t size) {
     34   ringbuffer_t* p = osi_calloc(sizeof(ringbuffer_t));
     35   if (p == 0)
     36     return NULL;
     37 
     38   p->base = osi_calloc(size);
     39   if (p->base == 0) {
     40     osi_free(p);
     41     return NULL;
     42   }
     43 
     44   p->head = p->tail = p->base;
     45   p->total = p->available = size;
     46 
     47   return p;
     48 }
     49 
     50 void ringbuffer_free(ringbuffer_t *rb) {
     51   if (rb != NULL)
     52     osi_free(rb->base);
     53   osi_free(rb);
     54 }
     55 
     56 size_t ringbuffer_available(const ringbuffer_t *rb) {
     57   assert(rb);
     58   return rb->available;
     59 }
     60 
     61 size_t ringbuffer_size(const ringbuffer_t *rb) {
     62   assert(rb);
     63   return rb->total - rb->available;
     64 }
     65 
     66 size_t ringbuffer_insert(ringbuffer_t *rb, const uint8_t *p, size_t length) {
     67   assert(rb);
     68   assert(p);
     69 
     70   if (length > ringbuffer_available(rb))
     71     length = ringbuffer_available(rb);
     72 
     73   for (size_t i = 0; i != length; ++i) {
     74     *rb->tail++ = *p++;
     75     if (rb->tail >= (rb->base + rb->total))
     76       rb->tail = rb->base;
     77   }
     78 
     79   rb->available -= length;
     80   return length;
     81 }
     82 
     83 size_t ringbuffer_delete(ringbuffer_t *rb, size_t length) {
     84   assert(rb);
     85 
     86   if (length > ringbuffer_size(rb))
     87     length = ringbuffer_size(rb);
     88 
     89   rb->head += length;
     90   if (rb->head >= (rb->base + rb->total))
     91     rb->head -= rb->total;
     92 
     93   rb->available += length;
     94   return length;
     95 }
     96 
     97 size_t ringbuffer_peek(const ringbuffer_t *rb, uint8_t *p, size_t length) {
     98   assert(rb);
     99   assert(p);
    100 
    101   uint8_t *b = rb->head;
    102   size_t copied = 0;
    103 
    104   while (copied < length && copied < ringbuffer_size(rb)) {
    105     *p++ = *b++;
    106     if (b >= (rb->base + rb->total))
    107       b = rb->base;
    108     ++copied;
    109   }
    110 
    111   return copied;
    112 }
    113 
    114 size_t ringbuffer_pop(ringbuffer_t *rb, uint8_t *p, size_t length) {
    115   assert(rb);
    116   assert(p);
    117 
    118   const size_t copied = ringbuffer_peek(rb, p, length);
    119   rb->head += copied;
    120   if (rb->head >= (rb->base + rb->total))
    121     rb->head -= rb->total;
    122 
    123   rb->available += copied;
    124   return copied;
    125 }
    126