1e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent/* 2e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved. 3e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent * 4e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent * Use of this source code is governed by a BSD-style license 5e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent * that can be found in the LICENSE file in the root of the source 6e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent * tree. An additional intellectual property rights grant can be found 7e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent * in the file PATENTS. All contributing project authors may 8e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent * be found in the AUTHORS file in the root of the source tree. 9e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent */ 10e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 11c55a96383497a772a307b346368133960b02ad03Eric Laurent// A ring buffer to hold arbitrary data. Provides no thread safety. Unless 12c55a96383497a772a307b346368133960b02ad03Eric Laurent// otherwise specified, functions return 0 on success and -1 on error. 13c55a96383497a772a307b346368133960b02ad03Eric Laurent 14c55a96383497a772a307b346368133960b02ad03Eric Laurent#include "ring_buffer.h" 15e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 16c55a96383497a772a307b346368133960b02ad03Eric Laurent#include <stddef.h> // size_t 17e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent#include <stdlib.h> 18e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent#include <string.h> 19c55a96383497a772a307b346368133960b02ad03Eric Laurent 20c55a96383497a772a307b346368133960b02ad03Eric Laurentenum Wrap { 21c55a96383497a772a307b346368133960b02ad03Eric Laurent SAME_WRAP, 22c55a96383497a772a307b346368133960b02ad03Eric Laurent DIFF_WRAP 23c55a96383497a772a307b346368133960b02ad03Eric Laurent}; 24e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 25e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurenttypedef struct { 26c55a96383497a772a307b346368133960b02ad03Eric Laurent size_t read_pos; 27c55a96383497a772a307b346368133960b02ad03Eric Laurent size_t write_pos; 28c55a96383497a772a307b346368133960b02ad03Eric Laurent size_t element_count; 29c55a96383497a772a307b346368133960b02ad03Eric Laurent size_t element_size; 30c55a96383497a772a307b346368133960b02ad03Eric Laurent enum Wrap rw_wrap; 31c55a96383497a772a307b346368133960b02ad03Eric Laurent char* data; 32e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent} buf_t; 33e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 34c55a96383497a772a307b346368133960b02ad03Eric Laurent// Get address of region(s) from which we can read data. 35c55a96383497a772a307b346368133960b02ad03Eric Laurent// If the region is contiguous, |data_ptr_bytes_2| will be zero. 36c55a96383497a772a307b346368133960b02ad03Eric Laurent// If non-contiguous, |data_ptr_bytes_2| will be the size in bytes of the second 37c55a96383497a772a307b346368133960b02ad03Eric Laurent// region. Returns room available to be read or |element_count|, whichever is 38c55a96383497a772a307b346368133960b02ad03Eric Laurent// smaller. 39c55a96383497a772a307b346368133960b02ad03Eric Laurentstatic size_t GetBufferReadRegions(buf_t* buf, 40c55a96383497a772a307b346368133960b02ad03Eric Laurent size_t element_count, 41c55a96383497a772a307b346368133960b02ad03Eric Laurent void** data_ptr_1, 42c55a96383497a772a307b346368133960b02ad03Eric Laurent size_t* data_ptr_bytes_1, 43c55a96383497a772a307b346368133960b02ad03Eric Laurent void** data_ptr_2, 44c55a96383497a772a307b346368133960b02ad03Eric Laurent size_t* data_ptr_bytes_2) { 45c55a96383497a772a307b346368133960b02ad03Eric Laurent 46c55a96383497a772a307b346368133960b02ad03Eric Laurent const size_t readable_elements = WebRtc_available_read(buf); 47c55a96383497a772a307b346368133960b02ad03Eric Laurent const size_t read_elements = (readable_elements < element_count ? 48c55a96383497a772a307b346368133960b02ad03Eric Laurent readable_elements : element_count); 49c55a96383497a772a307b346368133960b02ad03Eric Laurent const size_t margin = buf->element_count - buf->read_pos; 50c55a96383497a772a307b346368133960b02ad03Eric Laurent 51c55a96383497a772a307b346368133960b02ad03Eric Laurent // Check to see if read is not contiguous. 52c55a96383497a772a307b346368133960b02ad03Eric Laurent if (read_elements > margin) { 53c55a96383497a772a307b346368133960b02ad03Eric Laurent // Write data in two blocks that wrap the buffer. 54c55a96383497a772a307b346368133960b02ad03Eric Laurent *data_ptr_1 = buf->data + buf->read_pos * buf->element_size; 55c55a96383497a772a307b346368133960b02ad03Eric Laurent *data_ptr_bytes_1 = margin * buf->element_size; 56c55a96383497a772a307b346368133960b02ad03Eric Laurent *data_ptr_2 = buf->data; 57c55a96383497a772a307b346368133960b02ad03Eric Laurent *data_ptr_bytes_2 = (read_elements - margin) * buf->element_size; 58c55a96383497a772a307b346368133960b02ad03Eric Laurent } else { 59c55a96383497a772a307b346368133960b02ad03Eric Laurent *data_ptr_1 = buf->data + buf->read_pos * buf->element_size; 60c55a96383497a772a307b346368133960b02ad03Eric Laurent *data_ptr_bytes_1 = read_elements * buf->element_size; 61c55a96383497a772a307b346368133960b02ad03Eric Laurent *data_ptr_2 = NULL; 62c55a96383497a772a307b346368133960b02ad03Eric Laurent *data_ptr_bytes_2 = 0; 63c55a96383497a772a307b346368133960b02ad03Eric Laurent } 64c55a96383497a772a307b346368133960b02ad03Eric Laurent 65c55a96383497a772a307b346368133960b02ad03Eric Laurent return read_elements; 66c55a96383497a772a307b346368133960b02ad03Eric Laurent} 67e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 68c55a96383497a772a307b346368133960b02ad03Eric Laurentint WebRtc_CreateBuffer(void** handle, 69c55a96383497a772a307b346368133960b02ad03Eric Laurent size_t element_count, 70c55a96383497a772a307b346368133960b02ad03Eric Laurent size_t element_size) { 71c55a96383497a772a307b346368133960b02ad03Eric Laurent buf_t* self = NULL; 72e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 73c55a96383497a772a307b346368133960b02ad03Eric Laurent if (handle == NULL) { 74c55a96383497a772a307b346368133960b02ad03Eric Laurent return -1; 75c55a96383497a772a307b346368133960b02ad03Eric Laurent } 76e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 77c55a96383497a772a307b346368133960b02ad03Eric Laurent self = malloc(sizeof(buf_t)); 78c55a96383497a772a307b346368133960b02ad03Eric Laurent if (self == NULL) { 79c55a96383497a772a307b346368133960b02ad03Eric Laurent return -1; 80c55a96383497a772a307b346368133960b02ad03Eric Laurent } 81c55a96383497a772a307b346368133960b02ad03Eric Laurent *handle = self; 82e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 83c55a96383497a772a307b346368133960b02ad03Eric Laurent self->data = malloc(element_count * element_size); 84c55a96383497a772a307b346368133960b02ad03Eric Laurent if (self->data == NULL) { 85c55a96383497a772a307b346368133960b02ad03Eric Laurent free(self); 86c55a96383497a772a307b346368133960b02ad03Eric Laurent self = NULL; 87c55a96383497a772a307b346368133960b02ad03Eric Laurent return -1; 88c55a96383497a772a307b346368133960b02ad03Eric Laurent } 89e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 90c55a96383497a772a307b346368133960b02ad03Eric Laurent self->element_count = element_count; 91c55a96383497a772a307b346368133960b02ad03Eric Laurent self->element_size = element_size; 92c55a96383497a772a307b346368133960b02ad03Eric Laurent 93c55a96383497a772a307b346368133960b02ad03Eric Laurent return 0; 94e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent} 95e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 96c55a96383497a772a307b346368133960b02ad03Eric Laurentint WebRtc_InitBuffer(void* handle) { 97c55a96383497a772a307b346368133960b02ad03Eric Laurent buf_t* self = (buf_t*) handle; 98e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 99c55a96383497a772a307b346368133960b02ad03Eric Laurent if (self == NULL) { 100c55a96383497a772a307b346368133960b02ad03Eric Laurent return -1; 101c55a96383497a772a307b346368133960b02ad03Eric Laurent } 102e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 103c55a96383497a772a307b346368133960b02ad03Eric Laurent self->read_pos = 0; 104c55a96383497a772a307b346368133960b02ad03Eric Laurent self->write_pos = 0; 105c55a96383497a772a307b346368133960b02ad03Eric Laurent self->rw_wrap = SAME_WRAP; 106e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 107c55a96383497a772a307b346368133960b02ad03Eric Laurent // Initialize buffer to zeros 108c55a96383497a772a307b346368133960b02ad03Eric Laurent memset(self->data, 0, self->element_count * self->element_size); 109c55a96383497a772a307b346368133960b02ad03Eric Laurent 110c55a96383497a772a307b346368133960b02ad03Eric Laurent return 0; 111e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent} 112e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 113c55a96383497a772a307b346368133960b02ad03Eric Laurentint WebRtc_FreeBuffer(void* handle) { 114c55a96383497a772a307b346368133960b02ad03Eric Laurent buf_t* self = (buf_t*) handle; 115e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 116c55a96383497a772a307b346368133960b02ad03Eric Laurent if (self == NULL) { 117c55a96383497a772a307b346368133960b02ad03Eric Laurent return -1; 118c55a96383497a772a307b346368133960b02ad03Eric Laurent } 119e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 120c55a96383497a772a307b346368133960b02ad03Eric Laurent free(self->data); 121c55a96383497a772a307b346368133960b02ad03Eric Laurent free(self); 122e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 123c55a96383497a772a307b346368133960b02ad03Eric Laurent return 0; 124e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent} 125e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 126c55a96383497a772a307b346368133960b02ad03Eric Laurentsize_t WebRtc_ReadBuffer(void* handle, 127c55a96383497a772a307b346368133960b02ad03Eric Laurent void** data_ptr, 128c55a96383497a772a307b346368133960b02ad03Eric Laurent void* data, 129c55a96383497a772a307b346368133960b02ad03Eric Laurent size_t element_count) { 130e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 131c55a96383497a772a307b346368133960b02ad03Eric Laurent buf_t* self = (buf_t*) handle; 132e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 133c55a96383497a772a307b346368133960b02ad03Eric Laurent if (self == NULL) { 134c55a96383497a772a307b346368133960b02ad03Eric Laurent return 0; 135c55a96383497a772a307b346368133960b02ad03Eric Laurent } 136c55a96383497a772a307b346368133960b02ad03Eric Laurent if (data == NULL) { 137c55a96383497a772a307b346368133960b02ad03Eric Laurent return 0; 138c55a96383497a772a307b346368133960b02ad03Eric Laurent } 139c55a96383497a772a307b346368133960b02ad03Eric Laurent if (data_ptr == NULL) { 140c55a96383497a772a307b346368133960b02ad03Eric Laurent return 0; 141c55a96383497a772a307b346368133960b02ad03Eric Laurent } 142c55a96383497a772a307b346368133960b02ad03Eric Laurent 143c55a96383497a772a307b346368133960b02ad03Eric Laurent { 144c55a96383497a772a307b346368133960b02ad03Eric Laurent void* buf_ptr_1 = NULL; 145c55a96383497a772a307b346368133960b02ad03Eric Laurent void* buf_ptr_2 = NULL; 146c55a96383497a772a307b346368133960b02ad03Eric Laurent size_t buf_ptr_bytes_1 = 0; 147c55a96383497a772a307b346368133960b02ad03Eric Laurent size_t buf_ptr_bytes_2 = 0; 148c55a96383497a772a307b346368133960b02ad03Eric Laurent const size_t read_count = GetBufferReadRegions(self, 149c55a96383497a772a307b346368133960b02ad03Eric Laurent element_count, 150c55a96383497a772a307b346368133960b02ad03Eric Laurent &buf_ptr_1, 151c55a96383497a772a307b346368133960b02ad03Eric Laurent &buf_ptr_bytes_1, 152c55a96383497a772a307b346368133960b02ad03Eric Laurent &buf_ptr_2, 153c55a96383497a772a307b346368133960b02ad03Eric Laurent &buf_ptr_bytes_2); 154c55a96383497a772a307b346368133960b02ad03Eric Laurent 155c55a96383497a772a307b346368133960b02ad03Eric Laurent if (buf_ptr_bytes_2 > 0) { 156c55a96383497a772a307b346368133960b02ad03Eric Laurent // We have a wrap around when reading the buffer. Copy the buffer data to 157c55a96383497a772a307b346368133960b02ad03Eric Laurent // |data| and point to it. 158c55a96383497a772a307b346368133960b02ad03Eric Laurent memcpy(data, buf_ptr_1, buf_ptr_bytes_1); 159c55a96383497a772a307b346368133960b02ad03Eric Laurent memcpy(((char*) data) + buf_ptr_bytes_1, buf_ptr_2, buf_ptr_bytes_2); 160c55a96383497a772a307b346368133960b02ad03Eric Laurent *data_ptr = data; 161c55a96383497a772a307b346368133960b02ad03Eric Laurent } else { 162c55a96383497a772a307b346368133960b02ad03Eric Laurent *data_ptr = buf_ptr_1; 163e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } 164e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 165c55a96383497a772a307b346368133960b02ad03Eric Laurent // Update read position 166c55a96383497a772a307b346368133960b02ad03Eric Laurent WebRtc_MoveReadPtr(handle, (int) read_count); 167e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 168c55a96383497a772a307b346368133960b02ad03Eric Laurent return read_count; 169c55a96383497a772a307b346368133960b02ad03Eric Laurent } 170e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent} 171e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 172c55a96383497a772a307b346368133960b02ad03Eric Laurentsize_t WebRtc_WriteBuffer(void* handle, 173c55a96383497a772a307b346368133960b02ad03Eric Laurent const void* data, 174c55a96383497a772a307b346368133960b02ad03Eric Laurent size_t element_count) { 175e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 176c55a96383497a772a307b346368133960b02ad03Eric Laurent buf_t* self = (buf_t*) handle; 177e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 178c55a96383497a772a307b346368133960b02ad03Eric Laurent if (self == NULL) { 179c55a96383497a772a307b346368133960b02ad03Eric Laurent return 0; 180c55a96383497a772a307b346368133960b02ad03Eric Laurent } 181c55a96383497a772a307b346368133960b02ad03Eric Laurent if (data == NULL) { 182c55a96383497a772a307b346368133960b02ad03Eric Laurent return 0; 183c55a96383497a772a307b346368133960b02ad03Eric Laurent } 184c55a96383497a772a307b346368133960b02ad03Eric Laurent 185c55a96383497a772a307b346368133960b02ad03Eric Laurent { 186c55a96383497a772a307b346368133960b02ad03Eric Laurent const size_t free_elements = WebRtc_available_write(handle); 187c55a96383497a772a307b346368133960b02ad03Eric Laurent const size_t write_elements = (free_elements < element_count ? free_elements 188c55a96383497a772a307b346368133960b02ad03Eric Laurent : element_count); 189c55a96383497a772a307b346368133960b02ad03Eric Laurent size_t n = write_elements; 190c55a96383497a772a307b346368133960b02ad03Eric Laurent const size_t margin = self->element_count - self->write_pos; 191c55a96383497a772a307b346368133960b02ad03Eric Laurent 192c55a96383497a772a307b346368133960b02ad03Eric Laurent if (write_elements > margin) { 193c55a96383497a772a307b346368133960b02ad03Eric Laurent // Buffer wrap around when writing. 194c55a96383497a772a307b346368133960b02ad03Eric Laurent memcpy(self->data + self->write_pos * self->element_size, 195c55a96383497a772a307b346368133960b02ad03Eric Laurent data, margin * self->element_size); 196c55a96383497a772a307b346368133960b02ad03Eric Laurent self->write_pos = 0; 197c55a96383497a772a307b346368133960b02ad03Eric Laurent n -= margin; 198c55a96383497a772a307b346368133960b02ad03Eric Laurent self->rw_wrap = DIFF_WRAP; 199e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } 200c55a96383497a772a307b346368133960b02ad03Eric Laurent memcpy(self->data + self->write_pos * self->element_size, 201c55a96383497a772a307b346368133960b02ad03Eric Laurent ((const char*) data) + ((write_elements - n) * self->element_size), 202c55a96383497a772a307b346368133960b02ad03Eric Laurent n * self->element_size); 203c55a96383497a772a307b346368133960b02ad03Eric Laurent self->write_pos += n; 204e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 205c55a96383497a772a307b346368133960b02ad03Eric Laurent return write_elements; 206c55a96383497a772a307b346368133960b02ad03Eric Laurent } 207e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent} 208e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 209c55a96383497a772a307b346368133960b02ad03Eric Laurentint WebRtc_MoveReadPtr(void* handle, int element_count) { 210e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 211c55a96383497a772a307b346368133960b02ad03Eric Laurent buf_t* self = (buf_t*) handle; 212e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 213c55a96383497a772a307b346368133960b02ad03Eric Laurent if (self == NULL) { 214c55a96383497a772a307b346368133960b02ad03Eric Laurent return 0; 215c55a96383497a772a307b346368133960b02ad03Eric Laurent } 216e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 217c55a96383497a772a307b346368133960b02ad03Eric Laurent { 218c55a96383497a772a307b346368133960b02ad03Eric Laurent // We need to be able to take care of negative changes, hence use "int" 219c55a96383497a772a307b346368133960b02ad03Eric Laurent // instead of "size_t". 220c55a96383497a772a307b346368133960b02ad03Eric Laurent const int free_elements = (int) WebRtc_available_write(handle); 221c55a96383497a772a307b346368133960b02ad03Eric Laurent const int readable_elements = (int) WebRtc_available_read(handle); 222c55a96383497a772a307b346368133960b02ad03Eric Laurent int read_pos = (int) self->read_pos; 223c55a96383497a772a307b346368133960b02ad03Eric Laurent 224c55a96383497a772a307b346368133960b02ad03Eric Laurent if (element_count > readable_elements) { 225c55a96383497a772a307b346368133960b02ad03Eric Laurent element_count = readable_elements; 226c55a96383497a772a307b346368133960b02ad03Eric Laurent } 227c55a96383497a772a307b346368133960b02ad03Eric Laurent if (element_count < -free_elements) { 228c55a96383497a772a307b346368133960b02ad03Eric Laurent element_count = -free_elements; 229e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } 230e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 231c55a96383497a772a307b346368133960b02ad03Eric Laurent read_pos += element_count; 232c55a96383497a772a307b346368133960b02ad03Eric Laurent if (read_pos > (int) self->element_count) { 233c55a96383497a772a307b346368133960b02ad03Eric Laurent // Buffer wrap around. Restart read position and wrap indicator. 234c55a96383497a772a307b346368133960b02ad03Eric Laurent read_pos -= (int) self->element_count; 235c55a96383497a772a307b346368133960b02ad03Eric Laurent self->rw_wrap = SAME_WRAP; 236c55a96383497a772a307b346368133960b02ad03Eric Laurent } 237c55a96383497a772a307b346368133960b02ad03Eric Laurent if (read_pos < 0) { 238c55a96383497a772a307b346368133960b02ad03Eric Laurent // Buffer wrap around. Restart read position and wrap indicator. 239c55a96383497a772a307b346368133960b02ad03Eric Laurent read_pos += (int) self->element_count; 240c55a96383497a772a307b346368133960b02ad03Eric Laurent self->rw_wrap = DIFF_WRAP; 241c55a96383497a772a307b346368133960b02ad03Eric Laurent } 242e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 243c55a96383497a772a307b346368133960b02ad03Eric Laurent self->read_pos = (size_t) read_pos; 244e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 245c55a96383497a772a307b346368133960b02ad03Eric Laurent return element_count; 246c55a96383497a772a307b346368133960b02ad03Eric Laurent } 247c55a96383497a772a307b346368133960b02ad03Eric Laurent} 248e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 249c55a96383497a772a307b346368133960b02ad03Eric Laurentsize_t WebRtc_available_read(const void* handle) { 250c55a96383497a772a307b346368133960b02ad03Eric Laurent const buf_t* self = (buf_t*) handle; 251e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 252c55a96383497a772a307b346368133960b02ad03Eric Laurent if (self == NULL) { 253c55a96383497a772a307b346368133960b02ad03Eric Laurent return 0; 254c55a96383497a772a307b346368133960b02ad03Eric Laurent } 255e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 256c55a96383497a772a307b346368133960b02ad03Eric Laurent if (self->rw_wrap == SAME_WRAP) { 257c55a96383497a772a307b346368133960b02ad03Eric Laurent return self->write_pos - self->read_pos; 258c55a96383497a772a307b346368133960b02ad03Eric Laurent } else { 259c55a96383497a772a307b346368133960b02ad03Eric Laurent return self->element_count - self->read_pos + self->write_pos; 260c55a96383497a772a307b346368133960b02ad03Eric Laurent } 261e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent} 262e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 263c55a96383497a772a307b346368133960b02ad03Eric Laurentsize_t WebRtc_available_write(const void* handle) { 264c55a96383497a772a307b346368133960b02ad03Eric Laurent const buf_t* self = (buf_t*) handle; 265c55a96383497a772a307b346368133960b02ad03Eric Laurent 266c55a96383497a772a307b346368133960b02ad03Eric Laurent if (self == NULL) { 267c55a96383497a772a307b346368133960b02ad03Eric Laurent return 0; 268c55a96383497a772a307b346368133960b02ad03Eric Laurent } 269e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 270c55a96383497a772a307b346368133960b02ad03Eric Laurent return self->element_count - WebRtc_available_read(handle); 271e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent} 272