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