select_buf.c 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186
  1. /*
  2. * Copyright (C) 2005-2006 iptelorg GmbH
  3. *
  4. * This file is part of Kamailio, a free SIP server.
  5. *
  6. * Kamailio is free software; you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation; either version 2 of the License, or
  9. * (at your option) any later version
  10. *
  11. * Kamailio is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with this program; if not, write to the Free Software
  18. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  19. *
  20. */
  21. /*!
  22. * \file
  23. * \brief Kamailio core :: static buffer for select results (mma)
  24. * each process owns a separate space
  25. * each request starts using the buffer from the start
  26. * \ingroup core
  27. * Module: \ref core
  28. */
  29. #include <stdio.h>
  30. #include <stdlib.h>
  31. #include <string.h>
  32. #include <unistd.h>
  33. #include <ctype.h>
  34. #include "dprint.h"
  35. #include "mem/mem.h"
  36. #include "str.h"
  37. #include "ut.h"
  38. /*
  39. * Placeholder for the buffer
  40. *
  41. * two buffers are actually used to cover the different size requests
  42. * assuming that resize can move the result to newly allocated space
  43. * and comparing two selects from the script could require two static buffers
  44. *
  45. * if more static buffers need to be valid at the same time change
  46. * the following constant
  47. */
  48. #define MAX_BUFFERS 2
  49. #define BUFFER_GRANULARITY 256
  50. typedef struct stat_buffer_ {
  51. char *b;
  52. int size;
  53. int offset;
  54. } stat_buffer_t;
  55. static stat_buffer_t buffer[MAX_BUFFERS];
  56. static int active_buffer=-1;
  57. #define ALLOC_SIZE(req_size) (((req_size/BUFFER_GRANULARITY)+1)*BUFFER_GRANULARITY)
  58. static int allocate_buffer(int req_size) {
  59. void *b;
  60. int size=ALLOC_SIZE(req_size);
  61. if (buffer[active_buffer].b == NULL) {
  62. if ((buffer[active_buffer].b=pkg_malloc(size))==NULL)
  63. return 0;
  64. buffer[active_buffer].size=size;
  65. buffer[active_buffer].offset=0;
  66. return 1;
  67. }
  68. active_buffer = (active_buffer?active_buffer:MAX_BUFFERS)-1;
  69. if (buffer[active_buffer].size >= req_size) {
  70. buffer[active_buffer].offset = 0;
  71. return 1;
  72. }
  73. if ((b=pkg_realloc(buffer[active_buffer].b,size))) {
  74. buffer[active_buffer].b=b;
  75. buffer[active_buffer].size=size;
  76. buffer[active_buffer].offset=0;
  77. return 1;
  78. }
  79. return 0;
  80. }
  81. /*
  82. * Request for space from buffer
  83. *
  84. * Returns: NULL memory allocation failure (no more space)
  85. * pointer to the space on success
  86. */
  87. char* get_static_buffer(int req_size) {
  88. char *p = NULL;
  89. #ifdef EXTRA_DEBUG
  90. if ((active_buffer < 0) || (active_buffer > MAX_BUFFERS-1)) {
  91. LM_CRIT("buffers have not been initialized yet. "
  92. "Call reset_static_buffer() before executing "
  93. "a route block.\n");
  94. abort();
  95. }
  96. #endif
  97. if ((buffer[active_buffer].size >= buffer[active_buffer].offset + req_size)
  98. || (allocate_buffer(req_size))) {
  99. /* enough space in current buffer or allocation successful */
  100. p = buffer[active_buffer].b+buffer[active_buffer].offset;
  101. buffer[active_buffer].offset += req_size;
  102. return p;
  103. }
  104. return NULL;
  105. }
  106. /* Internal function - called before request is going to be processed
  107. *
  108. * Reset offset to unused space
  109. */
  110. int reset_static_buffer(void) {
  111. int i;
  112. if (active_buffer == -1) {
  113. memset(buffer, 0, sizeof(buffer));
  114. } else {
  115. for (i=0; i<MAX_BUFFERS; i++)
  116. buffer[i].offset=0;
  117. }
  118. active_buffer=0;
  119. return 0;
  120. }
  121. int str_to_static_buffer(str* res, str* s)
  122. {
  123. res->s = get_static_buffer(s->len);
  124. if (!res->s) return -1;
  125. memcpy(res->s, s->s, s->len);
  126. res->len = s->len;
  127. return 0;
  128. }
  129. int int_to_static_buffer(str* res, int val)
  130. {
  131. char *c;
  132. c = int2str(abs(val), &res->len);
  133. res->s = get_static_buffer(res->len+((val<0)?1:0));
  134. if (!res->s) return -1;
  135. if (val < 0) {
  136. res->s[0] = '-';
  137. memcpy(res->s+1, c, res->len);
  138. res->len++;
  139. }
  140. else {
  141. memcpy(res->s, c, res->len);
  142. }
  143. return 0;
  144. }
  145. int uint_to_static_buffer(str* res, unsigned int val)
  146. {
  147. char *c;
  148. c = int2str(val, &res->len);
  149. res->s = get_static_buffer(res->len);
  150. if (!res->s) return -1;
  151. memcpy(res->s, c, res->len);
  152. return 0;
  153. }
  154. int uint_to_static_buffer_ex(str* res, unsigned int val, int base, int pad)
  155. {
  156. char *c;
  157. c = int2str_base_0pad(val, &res->len, base, pad);
  158. res->s = get_static_buffer(res->len);
  159. if (!res->s) return -1;
  160. memcpy(res->s, c, res->len);
  161. return 0;
  162. }