/src/switch_buffer.c

https://github.com/tzuryby/mod_conference-admin · C · 349 lines · 249 code · 59 blank · 41 comment · 47 complexity · ca05395fd07761b4242696908665881e MD5 · raw file

  1. /*
  2. * FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
  3. * Copyright (C) 2005-2011, 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. static uint32_t buffer_id = 0;
  35. typedef enum {
  36. SWITCH_BUFFER_FLAG_DYNAMIC = (1 << 0)
  37. } switch_buffer_flag_t;
  38. struct switch_buffer {
  39. switch_byte_t *data;
  40. switch_byte_t *head;
  41. switch_size_t used;
  42. switch_size_t actually_used;
  43. switch_size_t datalen;
  44. switch_size_t max_len;
  45. switch_size_t blocksize;
  46. switch_mutex_t *mutex;
  47. uint32_t flags;
  48. uint32_t id;
  49. int32_t loops;
  50. };
  51. SWITCH_DECLARE(switch_status_t) switch_buffer_create(switch_memory_pool_t *pool, switch_buffer_t **buffer, switch_size_t max_len)
  52. {
  53. switch_buffer_t *new_buffer;
  54. if ((new_buffer = switch_core_alloc(pool, sizeof(switch_buffer_t))) != 0 && (new_buffer->data = switch_core_alloc(pool, max_len)) != 0) {
  55. new_buffer->datalen = max_len;
  56. new_buffer->id = buffer_id++;
  57. new_buffer->head = new_buffer->data;
  58. *buffer = new_buffer;
  59. return SWITCH_STATUS_SUCCESS;
  60. }
  61. return SWITCH_STATUS_MEMERR;
  62. }
  63. SWITCH_DECLARE(switch_status_t) switch_buffer_create_dynamic(switch_buffer_t **buffer, switch_size_t blocksize, switch_size_t start_len,
  64. switch_size_t max_len)
  65. {
  66. switch_buffer_t *new_buffer;
  67. if ((new_buffer = malloc(sizeof(*new_buffer)))) {
  68. memset(new_buffer, 0, sizeof(*new_buffer));
  69. if (start_len) {
  70. if (!(new_buffer->data = malloc(start_len))) {
  71. free(new_buffer);
  72. return SWITCH_STATUS_MEMERR;
  73. }
  74. memset(new_buffer->data, 0, start_len);
  75. }
  76. new_buffer->max_len = max_len;
  77. new_buffer->datalen = start_len;
  78. new_buffer->id = buffer_id++;
  79. new_buffer->blocksize = blocksize;
  80. new_buffer->head = new_buffer->data;
  81. switch_set_flag(new_buffer, SWITCH_BUFFER_FLAG_DYNAMIC);
  82. *buffer = new_buffer;
  83. return SWITCH_STATUS_SUCCESS;
  84. }
  85. return SWITCH_STATUS_MEMERR;
  86. }
  87. SWITCH_DECLARE(void) switch_buffer_add_mutex(switch_buffer_t *buffer, switch_mutex_t *mutex)
  88. {
  89. buffer->mutex = mutex;
  90. }
  91. SWITCH_DECLARE(void) switch_buffer_lock(switch_buffer_t *buffer)
  92. {
  93. if (buffer->mutex) {
  94. switch_mutex_lock(buffer->mutex);
  95. }
  96. }
  97. SWITCH_DECLARE(switch_status_t) switch_buffer_trylock(switch_buffer_t *buffer)
  98. {
  99. if (buffer->mutex) {
  100. return switch_mutex_lock(buffer->mutex);
  101. }
  102. return SWITCH_STATUS_FALSE;
  103. }
  104. SWITCH_DECLARE(void) switch_buffer_unlock(switch_buffer_t *buffer)
  105. {
  106. if (buffer->mutex) {
  107. switch_mutex_unlock(buffer->mutex);
  108. }
  109. }
  110. SWITCH_DECLARE(switch_size_t) switch_buffer_len(switch_buffer_t *buffer)
  111. {
  112. return buffer->datalen;
  113. }
  114. SWITCH_DECLARE(switch_size_t) switch_buffer_freespace(switch_buffer_t *buffer)
  115. {
  116. if (switch_test_flag(buffer, SWITCH_BUFFER_FLAG_DYNAMIC)) {
  117. if (buffer->max_len) {
  118. return (switch_size_t) (buffer->max_len - buffer->used);
  119. }
  120. return 1000000;
  121. }
  122. return (switch_size_t) (buffer->datalen - buffer->used);
  123. }
  124. SWITCH_DECLARE(switch_size_t) switch_buffer_inuse(switch_buffer_t *buffer)
  125. {
  126. return buffer->used;
  127. }
  128. SWITCH_DECLARE(switch_size_t) switch_buffer_toss(switch_buffer_t *buffer, switch_size_t datalen)
  129. {
  130. switch_size_t reading = 0;
  131. if (buffer->used < 1) {
  132. buffer->used = 0;
  133. return 0;
  134. } else if (buffer->used >= datalen) {
  135. reading = datalen;
  136. } else {
  137. reading = buffer->used;
  138. }
  139. buffer->used -= reading;
  140. buffer->head += reading;
  141. return buffer->used;
  142. }
  143. SWITCH_DECLARE(void) switch_buffer_set_loops(switch_buffer_t *buffer, int32_t loops)
  144. {
  145. buffer->loops = loops;
  146. }
  147. SWITCH_DECLARE(switch_size_t) switch_buffer_read_loop(switch_buffer_t *buffer, void *data, switch_size_t datalen)
  148. {
  149. switch_size_t len;
  150. if ((len = switch_buffer_read(buffer, data, datalen)) == 0) {
  151. if (buffer->loops > 0) {
  152. buffer->loops--;
  153. }
  154. if (buffer->loops == 0) {
  155. return 0;
  156. }
  157. buffer->head = buffer->data;
  158. buffer->used = buffer->actually_used;
  159. len = switch_buffer_read(buffer, data, datalen);
  160. }
  161. return len;
  162. }
  163. SWITCH_DECLARE(switch_size_t) switch_buffer_read(switch_buffer_t *buffer, void *data, switch_size_t datalen)
  164. {
  165. switch_size_t reading = 0;
  166. if (buffer->used < 1) {
  167. buffer->used = 0;
  168. return 0;
  169. } else if (buffer->used >= datalen) {
  170. reading = datalen;
  171. } else {
  172. reading = buffer->used;
  173. }
  174. memcpy(data, buffer->head, reading);
  175. buffer->used -= reading;
  176. buffer->head += reading;
  177. return reading;
  178. }
  179. SWITCH_DECLARE(switch_size_t) switch_buffer_peek(switch_buffer_t *buffer, void *data, switch_size_t datalen)
  180. {
  181. switch_size_t reading = 0;
  182. if (buffer->used < 1) {
  183. buffer->used = 0;
  184. return 0;
  185. } else if (buffer->used >= datalen) {
  186. reading = datalen;
  187. } else {
  188. reading = buffer->used;
  189. }
  190. memcpy(data, buffer->head, reading);
  191. return reading;
  192. }
  193. SWITCH_DECLARE(switch_size_t) switch_buffer_peek_zerocopy(switch_buffer_t *buffer, const void **ptr)
  194. {
  195. switch_size_t reading = 0;
  196. if (buffer->used < 1) {
  197. buffer->used = 0;
  198. return 0;
  199. } else {
  200. reading = buffer->used;
  201. }
  202. *ptr = buffer->head;
  203. return reading;
  204. }
  205. SWITCH_DECLARE(switch_size_t) switch_buffer_write(switch_buffer_t *buffer, const void *data, switch_size_t datalen)
  206. {
  207. switch_size_t freespace, actual_freespace;
  208. switch_assert(buffer->data != NULL);
  209. if (!datalen) {
  210. return buffer->used;
  211. }
  212. actual_freespace = buffer->datalen - buffer->actually_used;
  213. if (actual_freespace < datalen) {
  214. memmove(buffer->data, buffer->head, buffer->used);
  215. buffer->head = buffer->data;
  216. buffer->actually_used = buffer->used;
  217. }
  218. freespace = buffer->datalen - buffer->used;
  219. if (switch_test_flag(buffer, SWITCH_BUFFER_FLAG_DYNAMIC)) {
  220. if (freespace < datalen && (!buffer->max_len || (buffer->used + datalen <= buffer->max_len))) {
  221. switch_size_t new_size, new_block_size;
  222. void *tmp;
  223. new_size = buffer->datalen + datalen;
  224. new_block_size = buffer->datalen + buffer->blocksize;
  225. if (new_block_size > new_size) {
  226. new_size = new_block_size;
  227. }
  228. buffer->head = buffer->data;
  229. if (!(tmp = realloc(buffer->data, new_size))) {
  230. return 0;
  231. }
  232. buffer->data = tmp;
  233. buffer->head = buffer->data;
  234. buffer->datalen = new_size;
  235. }
  236. }
  237. freespace = buffer->datalen - buffer->used;
  238. if (freespace < datalen) {
  239. return 0;
  240. }
  241. memcpy(buffer->head + buffer->used, data, datalen);
  242. buffer->used += datalen;
  243. buffer->actually_used += datalen;
  244. return buffer->used;
  245. }
  246. SWITCH_DECLARE(void) switch_buffer_zero(switch_buffer_t *buffer)
  247. {
  248. switch_assert(buffer->data != NULL);
  249. buffer->used = 0;
  250. buffer->actually_used = 0;
  251. buffer->head = buffer->data;
  252. }
  253. SWITCH_DECLARE(switch_size_t) switch_buffer_zwrite(switch_buffer_t *buffer, const void *data, switch_size_t datalen)
  254. {
  255. switch_size_t w;
  256. if (!(w = switch_buffer_write(buffer, data, datalen))) {
  257. switch_buffer_zero(buffer);
  258. return switch_buffer_write(buffer, data, datalen);
  259. }
  260. return w;
  261. }
  262. SWITCH_DECLARE(switch_size_t) switch_buffer_slide_write(switch_buffer_t *buffer, const void *data, switch_size_t datalen)
  263. {
  264. switch_size_t w;
  265. if (!(w = switch_buffer_write(buffer, data, datalen))) {
  266. switch_buffer_toss(buffer, datalen);
  267. return switch_buffer_write(buffer, data, datalen);
  268. }
  269. return w;
  270. }
  271. SWITCH_DECLARE(void) switch_buffer_destroy(switch_buffer_t **buffer)
  272. {
  273. if (buffer && *buffer) {
  274. if ((switch_test_flag((*buffer), SWITCH_BUFFER_FLAG_DYNAMIC))) {
  275. switch_safe_free((*buffer)->data);
  276. free(*buffer);
  277. }
  278. *buffer = NULL;
  279. }
  280. }
  281. /* For Emacs:
  282. * Local Variables:
  283. * mode:c
  284. * indent-tabs-mode:t
  285. * tab-width:4
  286. * c-basic-offset:4
  287. * End:
  288. * For VIM:
  289. * vim:set softtabstop=4 shiftwidth=4 tabstop=4:
  290. */