189f5e411d9ef31436741288a2267e46dd744e273Andre Eisenbach/****************************************************************************** 289f5e411d9ef31436741288a2267e46dd744e273Andre Eisenbach * 35b790feeeb211c42bf78ca3ae9c26aa30e516765Jakub Pawlowski * Copyright 2015 Google Inc. 489f5e411d9ef31436741288a2267e46dd744e273Andre Eisenbach * 589f5e411d9ef31436741288a2267e46dd744e273Andre Eisenbach * Licensed under the Apache License, Version 2.0 (the "License"); 689f5e411d9ef31436741288a2267e46dd744e273Andre Eisenbach * you may not use this file except in compliance with the License. 789f5e411d9ef31436741288a2267e46dd744e273Andre Eisenbach * You may obtain a copy of the License at: 889f5e411d9ef31436741288a2267e46dd744e273Andre Eisenbach * 989f5e411d9ef31436741288a2267e46dd744e273Andre Eisenbach * http://www.apache.org/licenses/LICENSE-2.0 1089f5e411d9ef31436741288a2267e46dd744e273Andre Eisenbach * 1189f5e411d9ef31436741288a2267e46dd744e273Andre Eisenbach * Unless required by applicable law or agreed to in writing, software 1289f5e411d9ef31436741288a2267e46dd744e273Andre Eisenbach * distributed under the License is distributed on an "AS IS" BASIS, 1389f5e411d9ef31436741288a2267e46dd744e273Andre Eisenbach * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1489f5e411d9ef31436741288a2267e46dd744e273Andre Eisenbach * See the License for the specific language governing permissions and 1589f5e411d9ef31436741288a2267e46dd744e273Andre Eisenbach * limitations under the License. 1689f5e411d9ef31436741288a2267e46dd744e273Andre Eisenbach * 1789f5e411d9ef31436741288a2267e46dd744e273Andre Eisenbach ******************************************************************************/ 1889f5e411d9ef31436741288a2267e46dd744e273Andre Eisenbach 19f2af1c42ccb2f642b241c2261b42d0be61d45438Jack He#include <base/logging.h> 2089f5e411d9ef31436741288a2267e46dd744e273Andre Eisenbach#include <stdlib.h> 2189f5e411d9ef31436741288a2267e46dd744e273Andre Eisenbach 2289f5e411d9ef31436741288a2267e46dd744e273Andre Eisenbach#include "osi/include/allocator.h" 2389f5e411d9ef31436741288a2267e46dd744e273Andre Eisenbach#include "osi/include/ringbuffer.h" 2489f5e411d9ef31436741288a2267e46dd744e273Andre Eisenbach 2589f5e411d9ef31436741288a2267e46dd744e273Andre Eisenbachstruct ringbuffer_t { 2689f5e411d9ef31436741288a2267e46dd744e273Andre Eisenbach size_t total; 2789f5e411d9ef31436741288a2267e46dd744e273Andre Eisenbach size_t available; 28b55040cc6448a8847490da807d2b6362aa8cb8d9Myles Watson uint8_t* base; 29b55040cc6448a8847490da807d2b6362aa8cb8d9Myles Watson uint8_t* head; 30b55040cc6448a8847490da807d2b6362aa8cb8d9Myles Watson uint8_t* tail; 3189f5e411d9ef31436741288a2267e46dd744e273Andre Eisenbach}; 3289f5e411d9ef31436741288a2267e46dd744e273Andre Eisenbach 3389f5e411d9ef31436741288a2267e46dd744e273Andre Eisenbachringbuffer_t* ringbuffer_init(const size_t size) { 34b55040cc6448a8847490da807d2b6362aa8cb8d9Myles Watson ringbuffer_t* p = 35b55040cc6448a8847490da807d2b6362aa8cb8d9Myles Watson static_cast<ringbuffer_t*>(osi_calloc(sizeof(ringbuffer_t))); 3689f5e411d9ef31436741288a2267e46dd744e273Andre Eisenbach 37b55040cc6448a8847490da807d2b6362aa8cb8d9Myles Watson p->base = static_cast<uint8_t*>(osi_calloc(size)); 3889f5e411d9ef31436741288a2267e46dd744e273Andre Eisenbach p->head = p->tail = p->base; 3989f5e411d9ef31436741288a2267e46dd744e273Andre Eisenbach p->total = p->available = size; 4089f5e411d9ef31436741288a2267e46dd744e273Andre Eisenbach 4189f5e411d9ef31436741288a2267e46dd744e273Andre Eisenbach return p; 4289f5e411d9ef31436741288a2267e46dd744e273Andre Eisenbach} 4389f5e411d9ef31436741288a2267e46dd744e273Andre Eisenbach 44b55040cc6448a8847490da807d2b6362aa8cb8d9Myles Watsonvoid ringbuffer_free(ringbuffer_t* rb) { 45b55040cc6448a8847490da807d2b6362aa8cb8d9Myles Watson if (rb != NULL) osi_free(rb->base); 4689f5e411d9ef31436741288a2267e46dd744e273Andre Eisenbach osi_free(rb); 4789f5e411d9ef31436741288a2267e46dd744e273Andre Eisenbach} 4889f5e411d9ef31436741288a2267e46dd744e273Andre Eisenbach 49b55040cc6448a8847490da807d2b6362aa8cb8d9Myles Watsonsize_t ringbuffer_available(const ringbuffer_t* rb) { 50f2af1c42ccb2f642b241c2261b42d0be61d45438Jack He CHECK(rb); 5189f5e411d9ef31436741288a2267e46dd744e273Andre Eisenbach return rb->available; 5289f5e411d9ef31436741288a2267e46dd744e273Andre Eisenbach} 5389f5e411d9ef31436741288a2267e46dd744e273Andre Eisenbach 54b55040cc6448a8847490da807d2b6362aa8cb8d9Myles Watsonsize_t ringbuffer_size(const ringbuffer_t* rb) { 55f2af1c42ccb2f642b241c2261b42d0be61d45438Jack He CHECK(rb); 5689f5e411d9ef31436741288a2267e46dd744e273Andre Eisenbach return rb->total - rb->available; 5789f5e411d9ef31436741288a2267e46dd744e273Andre Eisenbach} 5889f5e411d9ef31436741288a2267e46dd744e273Andre Eisenbach 59b55040cc6448a8847490da807d2b6362aa8cb8d9Myles Watsonsize_t ringbuffer_insert(ringbuffer_t* rb, const uint8_t* p, size_t length) { 60f2af1c42ccb2f642b241c2261b42d0be61d45438Jack He CHECK(rb); 61f2af1c42ccb2f642b241c2261b42d0be61d45438Jack He CHECK(p); 6289f5e411d9ef31436741288a2267e46dd744e273Andre Eisenbach 63b55040cc6448a8847490da807d2b6362aa8cb8d9Myles Watson if (length > ringbuffer_available(rb)) length = ringbuffer_available(rb); 6489f5e411d9ef31436741288a2267e46dd744e273Andre Eisenbach 6589f5e411d9ef31436741288a2267e46dd744e273Andre Eisenbach for (size_t i = 0; i != length; ++i) { 6689f5e411d9ef31436741288a2267e46dd744e273Andre Eisenbach *rb->tail++ = *p++; 67b55040cc6448a8847490da807d2b6362aa8cb8d9Myles Watson if (rb->tail >= (rb->base + rb->total)) rb->tail = rb->base; 6889f5e411d9ef31436741288a2267e46dd744e273Andre Eisenbach } 6989f5e411d9ef31436741288a2267e46dd744e273Andre Eisenbach 7089f5e411d9ef31436741288a2267e46dd744e273Andre Eisenbach rb->available -= length; 7189f5e411d9ef31436741288a2267e46dd744e273Andre Eisenbach return length; 7289f5e411d9ef31436741288a2267e46dd744e273Andre Eisenbach} 7389f5e411d9ef31436741288a2267e46dd744e273Andre Eisenbach 74b55040cc6448a8847490da807d2b6362aa8cb8d9Myles Watsonsize_t ringbuffer_delete(ringbuffer_t* rb, size_t length) { 75f2af1c42ccb2f642b241c2261b42d0be61d45438Jack He CHECK(rb); 7689f5e411d9ef31436741288a2267e46dd744e273Andre Eisenbach 77b55040cc6448a8847490da807d2b6362aa8cb8d9Myles Watson if (length > ringbuffer_size(rb)) length = ringbuffer_size(rb); 7889f5e411d9ef31436741288a2267e46dd744e273Andre Eisenbach 7989f5e411d9ef31436741288a2267e46dd744e273Andre Eisenbach rb->head += length; 80b55040cc6448a8847490da807d2b6362aa8cb8d9Myles Watson if (rb->head >= (rb->base + rb->total)) rb->head -= rb->total; 8189f5e411d9ef31436741288a2267e46dd744e273Andre Eisenbach 8289f5e411d9ef31436741288a2267e46dd744e273Andre Eisenbach rb->available += length; 8389f5e411d9ef31436741288a2267e46dd744e273Andre Eisenbach return length; 8489f5e411d9ef31436741288a2267e46dd744e273Andre Eisenbach} 8589f5e411d9ef31436741288a2267e46dd744e273Andre Eisenbach 86b55040cc6448a8847490da807d2b6362aa8cb8d9Myles Watsonsize_t ringbuffer_peek(const ringbuffer_t* rb, off_t offset, uint8_t* p, 87b55040cc6448a8847490da807d2b6362aa8cb8d9Myles Watson size_t length) { 88f2af1c42ccb2f642b241c2261b42d0be61d45438Jack He CHECK(rb); 89f2af1c42ccb2f642b241c2261b42d0be61d45438Jack He CHECK(p); 90f2af1c42ccb2f642b241c2261b42d0be61d45438Jack He CHECK(offset >= 0); 91f2af1c42ccb2f642b241c2261b42d0be61d45438Jack He CHECK((size_t)offset <= ringbuffer_size(rb)); 9289f5e411d9ef31436741288a2267e46dd744e273Andre Eisenbach 93b55040cc6448a8847490da807d2b6362aa8cb8d9Myles Watson uint8_t* b = ((rb->head - rb->base + offset) % rb->total) + rb->base; 94b55040cc6448a8847490da807d2b6362aa8cb8d9Myles Watson const size_t bytes_to_copy = (offset + length > ringbuffer_size(rb)) 95b55040cc6448a8847490da807d2b6362aa8cb8d9Myles Watson ? ringbuffer_size(rb) - offset 96b55040cc6448a8847490da807d2b6362aa8cb8d9Myles Watson : length; 9789f5e411d9ef31436741288a2267e46dd744e273Andre Eisenbach 98b35c23483633826617d2312be805df93aeb9d8caSharvil Nanavati for (size_t copied = 0; copied < bytes_to_copy; ++copied) { 9989f5e411d9ef31436741288a2267e46dd744e273Andre Eisenbach *p++ = *b++; 100b55040cc6448a8847490da807d2b6362aa8cb8d9Myles Watson if (b >= (rb->base + rb->total)) b = rb->base; 10189f5e411d9ef31436741288a2267e46dd744e273Andre Eisenbach } 10289f5e411d9ef31436741288a2267e46dd744e273Andre Eisenbach 103b35c23483633826617d2312be805df93aeb9d8caSharvil Nanavati return bytes_to_copy; 10489f5e411d9ef31436741288a2267e46dd744e273Andre Eisenbach} 10589f5e411d9ef31436741288a2267e46dd744e273Andre Eisenbach 106b55040cc6448a8847490da807d2b6362aa8cb8d9Myles Watsonsize_t ringbuffer_pop(ringbuffer_t* rb, uint8_t* p, size_t length) { 107f2af1c42ccb2f642b241c2261b42d0be61d45438Jack He CHECK(rb); 108f2af1c42ccb2f642b241c2261b42d0be61d45438Jack He CHECK(p); 10989f5e411d9ef31436741288a2267e46dd744e273Andre Eisenbach 110b35c23483633826617d2312be805df93aeb9d8caSharvil Nanavati const size_t copied = ringbuffer_peek(rb, 0, p, length); 11189f5e411d9ef31436741288a2267e46dd744e273Andre Eisenbach rb->head += copied; 112b55040cc6448a8847490da807d2b6362aa8cb8d9Myles Watson if (rb->head >= (rb->base + rb->total)) rb->head -= rb->total; 11389f5e411d9ef31436741288a2267e46dd744e273Andre Eisenbach 11489f5e411d9ef31436741288a2267e46dd744e273Andre Eisenbach rb->available += copied; 11589f5e411d9ef31436741288a2267e46dd744e273Andre Eisenbach return copied; 11689f5e411d9ef31436741288a2267e46dd744e273Andre Eisenbach} 117