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