/libs/freetdm/src/ftdm_buffer.c

https://github.com/curriegrad2004/FreeSWITCH · C · 302 lines · 192 code · 60 blank · 50 comment · 42 complexity · e1f602ce3cfa23b5bc9b2d966e9b2a18 MD5 · raw file

  1. /*
  2. * Copyright (c) 2007-2012, Anthony Minessale II
  3. * All rights reserved.
  4. *
  5. * Redistribution and use in source and binary forms, with or without
  6. * modification, are permitted provided that the following conditions
  7. * are met:
  8. *
  9. * * Redistributions of source code must retain the above copyright
  10. * notice, this list of conditions and the following disclaimer.
  11. *
  12. * * Redistributions in binary form must reproduce the above copyright
  13. * notice, this list of conditions and the following disclaimer in the
  14. * documentation and/or other materials provided with the distribution.
  15. *
  16. * * Neither the name of the original author; nor the names of any contributors
  17. * may be used to endorse or promote products derived from this software
  18. * without specific prior written permission.
  19. *
  20. *
  21. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  22. * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  23. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  24. * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
  25. * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
  26. * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  27. * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
  28. * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
  29. * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
  30. * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  31. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  32. */
  33. #include "private/ftdm_core.h"
  34. #include "ftdm_buffer.h"
  35. static unsigned buffer_id = 0;
  36. struct ftdm_buffer {
  37. unsigned char *data;
  38. unsigned char *head;
  39. ftdm_size_t used;
  40. ftdm_size_t actually_used;
  41. ftdm_size_t datalen;
  42. ftdm_size_t max_len;
  43. ftdm_size_t blocksize;
  44. unsigned id;
  45. int loops;
  46. };
  47. FT_DECLARE(ftdm_status_t) ftdm_buffer_create(ftdm_buffer_t **buffer, ftdm_size_t blocksize, ftdm_size_t start_len, ftdm_size_t max_len)
  48. {
  49. ftdm_buffer_t *new_buffer;
  50. new_buffer = ftdm_malloc(sizeof(*new_buffer));
  51. if (new_buffer) {
  52. memset(new_buffer, 0, sizeof(*new_buffer));
  53. if (start_len) {
  54. new_buffer->data = ftdm_malloc(start_len);
  55. if (!new_buffer->data) {
  56. ftdm_safe_free(new_buffer);
  57. return FTDM_MEMERR;
  58. }
  59. memset(new_buffer->data, 0, start_len);
  60. }
  61. new_buffer->max_len = max_len;
  62. new_buffer->datalen = start_len;
  63. new_buffer->id = buffer_id++;
  64. new_buffer->blocksize = blocksize;
  65. new_buffer->head = new_buffer->data;
  66. *buffer = new_buffer;
  67. return FTDM_SUCCESS;
  68. }
  69. return FTDM_MEMERR;
  70. }
  71. FT_DECLARE(ftdm_size_t) ftdm_buffer_len(ftdm_buffer_t *buffer)
  72. {
  73. assert(buffer != NULL);
  74. return buffer->datalen;
  75. }
  76. FT_DECLARE(ftdm_size_t) ftdm_buffer_freespace(ftdm_buffer_t *buffer)
  77. {
  78. assert(buffer != NULL);
  79. if (buffer->max_len) {
  80. return (ftdm_size_t) (buffer->max_len - buffer->used);
  81. }
  82. return 1000000;
  83. }
  84. FT_DECLARE(ftdm_size_t) ftdm_buffer_inuse(ftdm_buffer_t *buffer)
  85. {
  86. assert(buffer != NULL);
  87. return buffer->used;
  88. }
  89. FT_DECLARE(ftdm_size_t) ftdm_buffer_seek(ftdm_buffer_t *buffer, ftdm_size_t datalen)
  90. {
  91. ftdm_size_t reading = 0;
  92. assert(buffer != NULL);
  93. if (buffer->used < 1) {
  94. buffer->used = 0;
  95. return 0;
  96. } else if (buffer->used >= datalen) {
  97. reading = datalen;
  98. } else {
  99. reading = buffer->used;
  100. }
  101. buffer->used = buffer->actually_used - reading;
  102. buffer->head = buffer->data + reading;
  103. return reading;
  104. }
  105. FT_DECLARE(ftdm_size_t) ftdm_buffer_toss(ftdm_buffer_t *buffer, ftdm_size_t datalen)
  106. {
  107. ftdm_size_t reading = 0;
  108. assert(buffer != NULL);
  109. if (buffer->used < 1) {
  110. buffer->used = 0;
  111. return 0;
  112. } else if (buffer->used >= datalen) {
  113. reading = datalen;
  114. } else {
  115. reading = buffer->used;
  116. }
  117. buffer->used -= reading;
  118. buffer->head += reading;
  119. return buffer->used;
  120. }
  121. FT_DECLARE(void) ftdm_buffer_set_loops(ftdm_buffer_t *buffer, int loops)
  122. {
  123. buffer->loops = loops;
  124. }
  125. FT_DECLARE(ftdm_size_t) ftdm_buffer_read_loop(ftdm_buffer_t *buffer, void *data, ftdm_size_t datalen)
  126. {
  127. ftdm_size_t len;
  128. if ((len = ftdm_buffer_read(buffer, data, datalen)) < datalen) {
  129. if (buffer->loops == 0) {
  130. return len;
  131. }
  132. buffer->head = buffer->data;
  133. buffer->used = buffer->actually_used;
  134. len = ftdm_buffer_read(buffer, (char*)data + len, datalen - len);
  135. buffer->loops--;
  136. }
  137. return len;
  138. }
  139. FT_DECLARE(ftdm_size_t) ftdm_buffer_read(ftdm_buffer_t *buffer, void *data, ftdm_size_t datalen)
  140. {
  141. ftdm_size_t reading = 0;
  142. assert(buffer != NULL);
  143. assert(data != NULL);
  144. if (buffer->used < 1) {
  145. buffer->used = 0;
  146. return 0;
  147. } else if (buffer->used >= datalen) {
  148. reading = datalen;
  149. } else {
  150. reading = buffer->used;
  151. }
  152. memcpy(data, buffer->head, reading);
  153. buffer->used -= reading;
  154. buffer->head += reading;
  155. /* if (buffer->id == 4) printf("%u o %d = %d\n", buffer->id, (unsigned)reading, (unsigned)buffer->used); */
  156. return reading;
  157. }
  158. FT_DECLARE(ftdm_size_t) ftdm_buffer_write(ftdm_buffer_t *buffer, const void *data, ftdm_size_t datalen)
  159. {
  160. ftdm_size_t freespace, actual_freespace;
  161. assert(buffer != NULL);
  162. assert(data != NULL);
  163. assert(buffer->data != NULL);
  164. if (!datalen) {
  165. return buffer->used;
  166. }
  167. actual_freespace = buffer->datalen - buffer->actually_used;
  168. if (actual_freespace < datalen && (!buffer->max_len || (buffer->used + datalen <= buffer->max_len))) {
  169. memmove(buffer->data, buffer->head, buffer->used);
  170. buffer->head = buffer->data;
  171. buffer->actually_used = buffer->used;
  172. }
  173. freespace = buffer->datalen - buffer->used;
  174. /*
  175. if (buffer->data != buffer->head) {
  176. memmove(buffer->data, buffer->head, buffer->used);
  177. buffer->head = buffer->data;
  178. }
  179. */
  180. if (freespace < datalen) {
  181. ftdm_size_t new_size, new_block_size;
  182. void *data;
  183. new_size = buffer->datalen + datalen;
  184. new_block_size = buffer->datalen + buffer->blocksize;
  185. if (new_block_size > new_size) {
  186. new_size = new_block_size;
  187. }
  188. buffer->head = buffer->data;
  189. data = realloc(buffer->data, new_size);
  190. if (!data) {
  191. return 0;
  192. }
  193. buffer->data = data;
  194. buffer->head = buffer->data;
  195. buffer->datalen = new_size;
  196. }
  197. freespace = buffer->datalen - buffer->used;
  198. if (freespace < datalen) {
  199. return 0;
  200. } else {
  201. memcpy(buffer->head + buffer->used, data, datalen);
  202. buffer->used += datalen;
  203. buffer->actually_used += datalen;
  204. }
  205. /* if (buffer->id == 4) printf("%u i %d = %d\n", buffer->id, (unsigned)datalen, (unsigned)buffer->used); */
  206. return buffer->used;
  207. }
  208. FT_DECLARE(void) ftdm_buffer_zero(ftdm_buffer_t *buffer)
  209. {
  210. assert(buffer != NULL);
  211. assert(buffer->data != NULL);
  212. buffer->used = 0;
  213. buffer->actually_used = 0;
  214. buffer->head = buffer->data;
  215. }
  216. FT_DECLARE(ftdm_size_t) ftdm_buffer_zwrite(ftdm_buffer_t *buffer, const void *data, ftdm_size_t datalen)
  217. {
  218. ftdm_size_t w;
  219. if (!(w = ftdm_buffer_write(buffer, data, datalen))) {
  220. ftdm_buffer_zero(buffer);
  221. return ftdm_buffer_write(buffer, data, datalen);
  222. }
  223. return w;
  224. }
  225. FT_DECLARE(void) ftdm_buffer_destroy(ftdm_buffer_t **buffer)
  226. {
  227. if (*buffer) {
  228. ftdm_safe_free((*buffer)->data);
  229. ftdm_safe_free(*buffer);
  230. }
  231. *buffer = NULL;
  232. }
  233. /* For Emacs:
  234. * Local Variables:
  235. * mode:c
  236. * indent-tabs-mode:t
  237. * tab-width:4
  238. * c-basic-offset:4
  239. * End:
  240. * For VIM:
  241. * vim:set softtabstop=4 shiftwidth=4 tabstop=4:
  242. */