FreeSWITCH API Documentation  1.7.0
switch_buffer.c
Go to the documentation of this file.
1 /*
2  * FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
3  * Copyright (C) 2005-2014, Anthony Minessale II <anthm@freeswitch.org>
4  *
5  * Version: MPL 1.1
6  *
7  * The contents of this file are subject to the Mozilla Public License Version
8  * 1.1 (the "License"); you may not use this file except in compliance with
9  * the License. You may obtain a copy of the License at
10  * http://www.mozilla.org/MPL/
11  *
12  * Software distributed under the License is distributed on an "AS IS" basis,
13  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
14  * for the specific language governing rights and limitations under the
15  * License.
16  *
17  * The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
18  *
19  * The Initial Developer of the Original Code is
20  * Anthony Minessale II <anthm@freeswitch.org>
21  * Portions created by the Initial Developer are Copyright (C)
22  * the Initial Developer. All Rights Reserved.
23  *
24  * Contributor(s):
25  *
26  * Anthony Minessale II <anthm@freeswitch.org>
27  *
28  *
29  * switch_buffer.c -- Data Buffering Code
30  *
31  */
32 #include <switch.h>
33 #include <switch_buffer.h>
34 
35 static uint32_t buffer_id = 0;
36 
37 typedef enum {
41 
42 struct switch_buffer {
51  uint32_t flags;
52  uint32_t id;
53  int32_t loops;
54 };
55 
57 {
59  return SWITCH_STATUS_FALSE;
60  }
61 
62  buffer->head = buffer->data;
63  buffer->used = buffer->actually_used = buffer->datalen;
64 
65  return SWITCH_STATUS_SUCCESS;
66 }
67 
69 {
71  return SWITCH_STATUS_FALSE;
72  }
73 
74  buffer->data = data;
75  buffer->datalen = datalen;
77 }
78 
80 {
81  switch_buffer_t *new_buffer;
82 
83  if ((new_buffer = switch_core_alloc(pool, sizeof(switch_buffer_t))) != 0) {
84  new_buffer->id = buffer_id++;
86  switch_buffer_set_partition_data(new_buffer, data, datalen);
87  *buffer = new_buffer;
88  return SWITCH_STATUS_SUCCESS;
89  }
90  return SWITCH_STATUS_MEMERR;
91 }
92 
94 {
95  switch_buffer_t *new_buffer;
96 
97  if ((new_buffer = switch_core_alloc(pool, sizeof(switch_buffer_t))) != 0 && (new_buffer->data = switch_core_alloc(pool, max_len)) != 0) {
98  new_buffer->datalen = max_len;
99  new_buffer->id = buffer_id++;
100  new_buffer->head = new_buffer->data;
101  *buffer = new_buffer;
102  return SWITCH_STATUS_SUCCESS;
103  }
104  return SWITCH_STATUS_MEMERR;
105 }
106 
108  switch_size_t max_len)
109 {
110  switch_buffer_t *new_buffer;
111 
112  if ((new_buffer = malloc(sizeof(*new_buffer)))) {
113  memset(new_buffer, 0, sizeof(*new_buffer));
114 
115  if (start_len) {
116  if (!(new_buffer->data = malloc(start_len))) {
117  free(new_buffer);
118  *buffer = NULL;
119  return SWITCH_STATUS_MEMERR;
120  }
121  memset(new_buffer->data, 0, start_len);
122  }
123 
124  new_buffer->max_len = max_len;
125  new_buffer->datalen = start_len;
126  new_buffer->id = buffer_id++;
127  new_buffer->blocksize = blocksize;
128  new_buffer->head = new_buffer->data;
130 
131  *buffer = new_buffer;
132  return SWITCH_STATUS_SUCCESS;
133  }
134  *buffer = NULL;
135  return SWITCH_STATUS_MEMERR;
136 }
137 
139 {
140  buffer->mutex = mutex;
141 }
142 
144 {
145  if (buffer->mutex) {
146  switch_mutex_lock(buffer->mutex);
147  }
148 }
149 
151 {
152  if (buffer->mutex) {
153  return switch_mutex_lock(buffer->mutex);
154  }
155  return SWITCH_STATUS_FALSE;
156 }
157 
159 {
160  if (buffer->mutex) {
161  switch_mutex_unlock(buffer->mutex);
162  }
163 }
164 
166 {
167  return buffer->datalen;
168 }
169 
171 {
173  if (buffer->max_len) {
174  return (switch_size_t) (buffer->max_len - buffer->used);
175  }
176  return 1000000;
177  }
178 
179  return (switch_size_t) (buffer->datalen - buffer->used);
180 }
181 
183 {
184  return buffer->used;
185 }
186 
188 {
189  switch_size_t reading = 0;
190 
191  if (buffer->used < 1) {
192  buffer->used = 0;
193  return 0;
194  } else if (buffer->used >= datalen) {
195  reading = datalen;
196  } else {
197  reading = buffer->used;
198  }
199 
200  buffer->used -= reading;
201  buffer->head += reading;
202 
203  return buffer->used;
204 }
205 
207 {
208  buffer->loops = loops;
209 }
210 
212 {
213  switch_size_t len;
214  if ((len = switch_buffer_read(buffer, data, datalen)) == 0) {
215  if (buffer->loops > 0) {
216  buffer->loops--;
217  }
218  if (buffer->loops == 0) {
219  return 0;
220  }
221  buffer->head = buffer->data;
222  buffer->used = buffer->actually_used;
223  len = switch_buffer_read(buffer, data, datalen);
224  }
225  return len;
226 }
227 
229 {
230  switch_size_t reading = 0;
231 
232  if (buffer->used < 1) {
233  buffer->used = 0;
234  return 0;
235  } else if (buffer->used >= datalen) {
236  reading = datalen;
237  } else {
238  reading = buffer->used;
239  }
240 
241  memcpy(data, buffer->head, reading);
242  buffer->used -= reading;
243  buffer->head += reading;
244 
245  return reading;
246 }
247 
249 {
250  switch_size_t reading = 0;
251 
252  if (buffer->used < 1) {
253  buffer->used = 0;
254  return 0;
255  } else if (buffer->used >= datalen) {
256  reading = datalen;
257  } else {
258  reading = buffer->used;
259  }
260 
261  memcpy(data, buffer->head, reading);
262 
263  return reading;
264 }
265 
267 {
268  switch_size_t reading = 0;
269 
270  if (buffer->used < 1) {
271  buffer->used = 0;
272  *ptr = NULL;
273  return 0;
274  } else {
275  reading = buffer->used;
276  }
277 
278  *ptr = buffer->head;
279 
280  return reading;
281 }
282 
284 {
285  switch_size_t freespace, actual_freespace;
286 
288  return 0;
289  }
290 
291  switch_assert(buffer->data != NULL);
292 
293  if (!datalen) {
294  return buffer->used;
295  }
296 
297  actual_freespace = buffer->datalen - buffer->actually_used;
298 
299  if (actual_freespace < datalen) {
300  memmove(buffer->data, buffer->head, buffer->used);
301  buffer->head = buffer->data;
302  buffer->actually_used = buffer->used;
303  }
304 
305  freespace = buffer->datalen - buffer->used;
306 
308  if (freespace < datalen && (!buffer->max_len || (buffer->used + datalen <= buffer->max_len))) {
309  switch_size_t new_size, new_block_size;
310  void *tmp;
311 
312  new_size = buffer->datalen + datalen;
313  new_block_size = buffer->datalen + buffer->blocksize;
314 
315  if (new_block_size > new_size) {
316  new_size = new_block_size;
317  }
318  buffer->head = buffer->data;
319  if (!(tmp = realloc(buffer->data, new_size))) {
320  return 0;
321  }
322  buffer->data = tmp;
323  buffer->head = buffer->data;
324  buffer->datalen = new_size;
325  }
326  }
327 
328  freespace = buffer->datalen - buffer->used;
329 
330  if (freespace < datalen) {
331  return 0;
332  }
333 
334  memcpy(buffer->head + buffer->used, data, datalen);
335  buffer->used += datalen;
336  buffer->actually_used += datalen;
337  return buffer->used;
338 }
339 
341 {
342  switch_assert(buffer->data != NULL);
343 
344  buffer->used = 0;
345  buffer->actually_used = 0;
346  buffer->head = buffer->data;
347 }
348 
350 {
351  switch_size_t w;
352 
354  return 0;
355  }
356 
357  if (!(w = switch_buffer_write(buffer, data, datalen))) {
358  switch_buffer_zero(buffer);
359  return switch_buffer_write(buffer, data, datalen);
360  }
361 
362  return w;
363 }
364 
366 {
367  switch_size_t w;
368 
370  return 0;
371  }
372 
373  if (!(w = switch_buffer_write(buffer, data, datalen))) {
374  switch_buffer_toss(buffer, datalen);
375  return switch_buffer_write(buffer, data, datalen);
376  }
377 
378  return w;
379 }
380 
382 {
383  if (buffer && *buffer) {
384  if ((switch_test_flag((*buffer), SWITCH_BUFFER_FLAG_DYNAMIC))) {
385  switch_safe_free((*buffer)->data);
386  free(*buffer);
387  }
388  *buffer = NULL;
389  }
390 }
391 
392 /* For Emacs:
393  * Local Variables:
394  * mode:c
395  * indent-tabs-mode:t
396  * tab-width:4
397  * c-basic-offset:4
398  * End:
399  * For VIM:
400  * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet:
401  */
switch_byte_t * head
Definition: switch_buffer.c:44
switch_size_t actually_used
Definition: switch_buffer.c:46
#define switch_set_flag(obj, flag)
Set a flag on an arbitrary object.
Definition: switch_utils.h:631
switch_size_t switch_buffer_peek_zerocopy(switch_buffer_t *buffer, const void **ptr)
switch_buffer_flag_t
Definition: switch_buffer.c:37
switch_memory_pool_t * pool
switch_size_t datalen
Definition: switch_buffer.c:47
void switch_buffer_unlock(switch_buffer_t *buffer)
switch_size_t switch_buffer_slide_write(switch_buffer_t *buffer, const void *data, switch_size_t datalen)
switch_size_t switch_buffer_freespace(switch_buffer_t *buffer)
switch_status_t switch_buffer_create(switch_memory_pool_t *pool, switch_buffer_t **buffer, switch_size_t max_len)
Definition: switch_buffer.c:93
void switch_buffer_lock(switch_buffer_t *buffer)
switch_size_t switch_buffer_inuse(switch_buffer_t *buffer)
uint8_t switch_byte_t
Definition: switch_types.h:246
switch_status_t switch_buffer_create_partition(switch_memory_pool_t *pool, switch_buffer_t **buffer, void *data, switch_size_t datalen)
Definition: switch_buffer.c:79
switch_status_t switch_mutex_unlock(switch_mutex_t *lock)
Definition: switch_apr.c:290
switch_size_t used
Definition: switch_buffer.c:45
switch_byte_t * data
Definition: switch_buffer.c:43
switch_status_t switch_mutex_lock(switch_mutex_t *lock)
Definition: switch_apr.c:285
static uint32_t buffer_id
Definition: switch_buffer.c:35
#define switch_core_alloc(_pool, _mem)
Allocate memory directly from a memory pool.
Definition: switch_core.h:682
switch_size_t blocksize
Definition: switch_buffer.c:49
switch_status_t switch_buffer_trylock(switch_buffer_t *buffer)
#define switch_safe_free(it)
Free a pointer and set it to NULL unless it already is NULL.
Definition: switch_utils.h:789
Data Buffering Code.
uintptr_t switch_size_t
switch_size_t switch_buffer_toss(switch_buffer_t *buffer, switch_size_t datalen)
switch_size_t switch_buffer_peek(switch_buffer_t *buffer, void *data, switch_size_t datalen)
switch_mutex_t * mutex
Definition: switch_buffer.c:50
switch_mutex_t * mutex
void switch_buffer_add_mutex(switch_buffer_t *buffer, switch_mutex_t *mutex)
switch_size_t max_len
Definition: switch_buffer.c:48
struct apr_thread_mutex_t switch_mutex_t
Definition: switch_apr.h:314
switch_status_t
Common return values.
switch_status_t switch_buffer_reset_partition_data(switch_buffer_t *buffer)
Definition: switch_buffer.c:56
switch_size_t switch_buffer_read_loop(switch_buffer_t *buffer, void *data, switch_size_t datalen)
Main Library Header.
switch_size_t switch_buffer_zwrite(switch_buffer_t *buffer, const void *data, switch_size_t datalen)
#define SWITCH_DECLARE(type)
switch_size_t switch_buffer_len(switch_buffer_t *buffer)
struct apr_pool_t switch_memory_pool_t
uint32_t flags
Definition: switch_buffer.c:51
#define switch_test_flag(obj, flag)
Test for the existance of a flag on an arbitary object.
Definition: switch_utils.h:624
void switch_buffer_set_loops(switch_buffer_t *buffer, int32_t loops)
#define switch_assert(expr)
switch_status_t switch_buffer_set_partition_data(switch_buffer_t *buffer, void *data, switch_size_t datalen)
Definition: switch_buffer.c:68
switch_size_t switch_buffer_read(switch_buffer_t *buffer, void *data, switch_size_t datalen)
void switch_buffer_destroy(switch_buffer_t **buffer)
Destroy the buffer.
memset(buf, 0, buflen)
switch_size_t switch_buffer_write(switch_buffer_t *buffer, const void *data, switch_size_t datalen)
switch_status_t switch_buffer_create_dynamic(switch_buffer_t **buffer, switch_size_t blocksize, switch_size_t start_len, switch_size_t max_len)
void switch_buffer_zero(switch_buffer_t *buffer)