RTS API Documentation  1.10.11
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 
56 
58 {
59  return buffer->head;
60 }
61 
63 {
65  return SWITCH_STATUS_FALSE;
66  }
67 
68  buffer->head = buffer->data;
69  buffer->used = buffer->actually_used = buffer->datalen;
70 
71  return SWITCH_STATUS_SUCCESS;
72 }
73 
75 {
77  return SWITCH_STATUS_FALSE;
78  }
79 
80  buffer->data = data;
81  buffer->datalen = datalen;
83 }
84 
86 {
87  switch_buffer_t *new_buffer;
88 
89  if ((new_buffer = switch_core_alloc(pool, sizeof(switch_buffer_t))) != 0) {
90  new_buffer->id = buffer_id++;
92  switch_buffer_set_partition_data(new_buffer, data, datalen);
93  *buffer = new_buffer;
94  return SWITCH_STATUS_SUCCESS;
95  }
96  return SWITCH_STATUS_MEMERR;
97 }
98 
100 {
101  switch_buffer_t *new_buffer;
102 
103  if ((new_buffer = switch_core_alloc(pool, sizeof(switch_buffer_t))) != 0 && (new_buffer->data = switch_core_alloc(pool, max_len)) != 0) {
104  new_buffer->datalen = max_len;
105  new_buffer->id = buffer_id++;
106  new_buffer->head = new_buffer->data;
107  *buffer = new_buffer;
108  return SWITCH_STATUS_SUCCESS;
109  }
110  return SWITCH_STATUS_MEMERR;
111 }
112 
115 {
116  switch_buffer_t *new_buffer;
117 
118  if ((new_buffer = malloc(sizeof(*new_buffer)))) {
119  memset(new_buffer, 0, sizeof(*new_buffer));
120 
121  if (!start_len) {
122  start_len = 250;
123  }
124 
125  if (!blocksize) {
126  blocksize = start_len;
127  }
128 
129  if (!(new_buffer->data = malloc(start_len))) {
130  free(new_buffer);
131  *buffer = NULL;
132  return SWITCH_STATUS_MEMERR;
133  }
134 
135  memset(new_buffer->data, 0, start_len);
136 
137  new_buffer->max_len = max_len;
138  new_buffer->datalen = start_len;
139  new_buffer->id = buffer_id++;
140  new_buffer->blocksize = blocksize;
141  new_buffer->head = new_buffer->data;
143 
144  *buffer = new_buffer;
145  return SWITCH_STATUS_SUCCESS;
146  }
147  *buffer = NULL;
148  return SWITCH_STATUS_MEMERR;
149 }
150 
152 {
153  buffer->mutex = mutex;
154 }
155 
157 {
158  if (buffer->mutex) {
159  switch_mutex_lock(buffer->mutex);
160  }
161 }
162 
164 {
165  if (buffer->mutex) {
166  return switch_mutex_lock(buffer->mutex);
167  }
168  return SWITCH_STATUS_FALSE;
169 }
170 
172 {
173  if (buffer->mutex) {
174  switch_mutex_unlock(buffer->mutex);
175  }
176 }
177 
179 {
180  return buffer->datalen;
181 }
182 
184 {
186  if (buffer->max_len) {
187  return (switch_size_t) (buffer->max_len - buffer->used);
188  }
189  return 1000000;
190  }
191 
192  return (switch_size_t) (buffer->datalen - buffer->used);
193 }
194 
196 {
197  return buffer->used;
198 }
199 
201 {
202  switch_size_t reading = 0;
203 
204  if (buffer->used < 1) {
205  buffer->used = 0;
206  return 0;
207  } else if (buffer->used >= datalen) {
208  reading = datalen;
209  } else {
210  reading = buffer->used;
211  }
212 
213  buffer->used -= reading;
214  buffer->head += reading;
215 
216  return buffer->used;
217 }
218 
220 {
221  buffer->loops = loops;
222 }
223 
225 {
226  switch_size_t len;
227  if ((len = switch_buffer_read(buffer, data, datalen)) == 0) {
228  if (buffer->loops > 0) {
229  buffer->loops--;
230  }
231  if (buffer->loops == 0) {
232  return 0;
233  }
234  buffer->head = buffer->data;
235  buffer->used = buffer->actually_used;
236  len = switch_buffer_read(buffer, data, datalen);
237  }
238  return len;
239 }
240 
242 {
243  switch_size_t reading = 0;
244 
245  if (buffer->used < 1) {
246  buffer->used = 0;
247  return 0;
248  } else if (buffer->used >= datalen) {
249  reading = datalen;
250  } else {
251  reading = buffer->used;
252  }
253 
254  memcpy(data, buffer->head, reading);
255  buffer->used -= reading;
256  buffer->head += reading;
257 
258  return reading;
259 }
260 
262 {
263  switch_size_t reading = 0;
264 
265  if (buffer->used < 1) {
266  buffer->used = 0;
267  return 0;
268  } else if (buffer->used >= datalen) {
269  reading = datalen;
270  } else {
271  reading = buffer->used;
272  }
273 
274  memcpy(data, buffer->head, reading);
275 
276  return reading;
277 }
278 
280 {
281  switch_size_t reading = 0;
282 
283  if (buffer->used < 1) {
284  buffer->used = 0;
285  *ptr = NULL;
286  return 0;
287  } else {
288  reading = buffer->used;
289  }
290 
291  *ptr = buffer->head;
292 
293  return reading;
294 }
295 
297 {
298  switch_size_t freespace, actual_freespace;
299 
301  return 0;
302  }
303 
304  switch_assert(buffer->data != NULL);
305 
306  if (!datalen) {
307  return buffer->used;
308  }
309 
310  actual_freespace = buffer->datalen - buffer->actually_used;
311 
312  if (actual_freespace < datalen) {
313  memmove(buffer->data, buffer->head, buffer->used);
314  buffer->head = buffer->data;
315  buffer->actually_used = buffer->used;
316  }
317 
318  freespace = buffer->datalen - buffer->used;
319 
321  if (freespace < datalen && (!buffer->max_len || (buffer->used + datalen <= buffer->max_len))) {
322  switch_size_t new_size, new_block_size;
323  void *tmp;
324 
325  new_size = buffer->datalen + datalen;
326  new_block_size = buffer->datalen + buffer->blocksize;
327 
328  if (new_block_size > new_size) {
329  new_size = new_block_size;
330  }
331  buffer->head = buffer->data;
332  if (!(tmp = realloc(buffer->data, new_size))) {
333  return 0;
334  }
335  buffer->data = tmp;
336  buffer->head = buffer->data;
337  buffer->datalen = new_size;
338  }
339  }
340 
341  freespace = buffer->datalen - buffer->used;
342 
343  if (freespace < datalen) {
344  return 0;
345  }
346 
347  if (data) {
348  memcpy(buffer->head + buffer->used, data, datalen);
349  } else {
350  memset(buffer->head + buffer->used, 0, datalen);
351  }
352 
353  buffer->used += datalen;
354  buffer->actually_used += datalen;
355  return buffer->used;
356 }
357 
359 {
360  switch_assert(buffer->data != NULL);
361 
362  buffer->used = 0;
363  buffer->actually_used = 0;
364  buffer->head = buffer->data;
365 }
366 
368 {
369  switch_size_t w;
370 
372  return 0;
373  }
374 
375  if (!(w = switch_buffer_write(buffer, data, datalen))) {
376  switch_buffer_zero(buffer);
377  return switch_buffer_write(buffer, data, datalen);
378  }
379 
380  return w;
381 }
382 
384 {
385  switch_size_t w;
386 
388  return 0;
389  }
390 
391  if (!(w = switch_buffer_write(buffer, data, datalen))) {
392  switch_buffer_toss(buffer, datalen);
393  return switch_buffer_write(buffer, data, datalen);
394  }
395 
396  return w;
397 }
398 
400 {
401  if (buffer && *buffer) {
402  if ((switch_test_flag((*buffer), SWITCH_BUFFER_FLAG_DYNAMIC))) {
403  switch_safe_free((*buffer)->data);
404  free(*buffer);
405  }
406  *buffer = NULL;
407  }
408 }
409 
410 /* For Emacs:
411  * Local Variables:
412  * mode:c
413  * indent-tabs-mode:t
414  * tab-width:4
415  * c-basic-offset:4
416  * End:
417  * For VIM:
418  * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet:
419  */
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:700
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:99
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:256
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:85
switch_status_t switch_mutex_unlock(switch_mutex_t *lock)
Definition: switch_apr.c:313
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:308
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:684
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:885
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
void switch_buffer_add_mutex(switch_buffer_t *buffer, switch_mutex_t *mutex)
struct fspr_thread_mutex_t switch_mutex_t
Definition: switch_apr.h:314
switch_size_t max_len
Definition: switch_buffer.c:48
switch_status_t
Common return values.
switch_status_t switch_buffer_reset_partition_data(switch_buffer_t *buffer)
Definition: switch_buffer.c:62
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)
char * buffer
Definition: switch_cJSON.h:153
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:693
void switch_buffer_set_loops(switch_buffer_t *buffer, int32_t loops)
struct fspr_pool_t switch_memory_pool_t
#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:74
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)
void * switch_buffer_get_head_pointer(switch_buffer_t *buffer)
Definition: switch_buffer.c:57
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)