vector.cc 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276
  1. /* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
  2. *
  3. * Gearmand String
  4. *
  5. * Copyright (C) 2011 Data Differential, http://datadifferential.com/
  6. *
  7. * Redistribution and use in source and binary forms, with or without
  8. * modification, are permitted provided that the following conditions are
  9. * met:
  10. *
  11. * * Redistributions of source code must retain the above copyright
  12. * notice, this list of conditions and the following disclaimer.
  13. *
  14. * * Redistributions in binary form must reproduce the above
  15. * copyright notice, this list of conditions and the following disclaimer
  16. * in the documentation and/or other materials provided with the
  17. * distribution.
  18. *
  19. * * The names of its contributors may not be used to endorse or
  20. * promote products derived from this software without specific prior
  21. * written permission.
  22. *
  23. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  24. * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  25. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  26. * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  27. * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  28. * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  29. * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  30. * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  31. * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  32. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  33. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  34. *
  35. */
  36. #include <libgearman/common.h>
  37. #include <cassert>
  38. #include <cstdlib>
  39. #include <cstring>
  40. #define GEARMAN_BLOCK_SIZE 1024*4
  41. inline static gearman_return_t _string_check(gearman_vector_st *string, const size_t need)
  42. {
  43. if (not string)
  44. return GEARMAN_INVALID_ARGUMENT;
  45. if (need && need > size_t(string->current_size - size_t(string->end - string->string)))
  46. {
  47. size_t current_offset= size_t(string->end - string->string);
  48. char *new_value;
  49. size_t adjust;
  50. size_t new_size;
  51. /* This is the block multiplier. To keep it larger and surive division errors we must round it up */
  52. adjust= (need - size_t(string->current_size - size_t(string->end - string->string))) / GEARMAN_BLOCK_SIZE;
  53. adjust++;
  54. new_size= sizeof(char) * size_t((adjust * GEARMAN_BLOCK_SIZE) + string->current_size);
  55. /* Test for overflow */
  56. if (new_size < need)
  57. {
  58. return GEARMAN_MEMORY_ALLOCATION_FAILURE;
  59. }
  60. new_value= static_cast<char *>(realloc(string->string, new_size));
  61. if (new_value == NULL)
  62. {
  63. return GEARMAN_MEMORY_ALLOCATION_FAILURE;
  64. }
  65. string->string= new_value;
  66. string->end= string->string + current_offset;
  67. string->current_size+= (GEARMAN_BLOCK_SIZE * adjust);
  68. }
  69. return GEARMAN_SUCCESS;
  70. }
  71. static inline void _init_string(gearman_vector_st *self)
  72. {
  73. self->current_size= 0;
  74. self->end= self->string= NULL;
  75. }
  76. gearman_vector_st *gearman_string_create(gearman_vector_st *self, const char *str, size_t initial_size)
  77. {
  78. if (not str)
  79. return NULL;
  80. self= gearman_string_create(self, initial_size);
  81. if (not self)
  82. return NULL;
  83. if (gearman_failed(gearman_string_append(self, str, initial_size)))
  84. {
  85. gearman_string_free(self);
  86. return NULL;
  87. }
  88. return self;
  89. }
  90. gearman_vector_st *gearman_string_create(gearman_vector_st *self, size_t initial_size)
  91. {
  92. /* Saving malloc calls :) */
  93. if (self)
  94. {
  95. gearman_set_allocated(self, false);
  96. }
  97. else
  98. {
  99. self= static_cast<gearman_vector_st *>(malloc(sizeof(gearman_vector_st)));
  100. if (not self)
  101. {
  102. return NULL;
  103. }
  104. gearman_set_allocated(self, true);
  105. }
  106. _init_string(self);
  107. if (gearman_failed(_string_check(self, initial_size)))
  108. {
  109. if (gearman_is_allocated(self))
  110. {
  111. free(self);
  112. }
  113. return NULL;
  114. }
  115. if (initial_size)
  116. self->string[0]= 0;
  117. return self;
  118. }
  119. gearman_vector_st *gearman_string_clone(const gearman_vector_st *self)
  120. {
  121. if (not self)
  122. return NULL;
  123. gearman_vector_st *clone= gearman_string_create(NULL, gearman_string_length(self));
  124. if (not clone)
  125. return NULL;
  126. if (gearman_string_length(self))
  127. {
  128. if (gearman_failed(gearman_string_append(clone, gearman_string_value(self), gearman_string_length(self))))
  129. {
  130. gearman_string_free(clone);
  131. return NULL;
  132. }
  133. }
  134. return clone;
  135. }
  136. gearman_return_t gearman_string_append_character(gearman_vector_st *string, char character)
  137. {
  138. gearman_return_t rc;
  139. if (gearman_failed(rc= _string_check(string, 1 +1))) // Null terminate
  140. {
  141. return rc;
  142. }
  143. *string->end= character;
  144. string->end++;
  145. *string->end= 0;
  146. return GEARMAN_SUCCESS;
  147. }
  148. gearman_return_t gearman_string_append(gearman_vector_st *string,
  149. const char *value, size_t length)
  150. {
  151. gearman_return_t rc;
  152. if (gearman_failed(rc= _string_check(string, length +1)))
  153. {
  154. return rc;
  155. }
  156. memcpy(string->end, value, length);
  157. string->end+= length;
  158. *string->end= 0; // Add a NULL
  159. return GEARMAN_SUCCESS;
  160. }
  161. char *gearman_string_c_copy(gearman_vector_st *string)
  162. {
  163. char *c_ptr;
  164. if (gearman_string_length(string) == 0)
  165. return NULL;
  166. c_ptr= static_cast<char *>(malloc((gearman_string_length(string) +1) * sizeof(char)));
  167. if (not c_ptr)
  168. return NULL;
  169. memcpy(c_ptr, gearman_string_value(string), gearman_string_length(string));
  170. c_ptr[gearman_string_length(string)]= 0;
  171. return c_ptr;
  172. }
  173. void gearman_string_reset(gearman_vector_st *string)
  174. {
  175. assert(string);
  176. string->end= string->string;
  177. }
  178. void gearman_string_free(gearman_vector_st *ptr)
  179. {
  180. if (not ptr)
  181. return;
  182. if (ptr->string)
  183. {
  184. free(ptr->string);
  185. }
  186. if (ptr->options.is_allocated)
  187. {
  188. free(ptr);
  189. }
  190. }
  191. gearman_return_t gearman_string_check(gearman_vector_st *string, size_t need)
  192. {
  193. return _string_check(string, need);
  194. }
  195. size_t gearman_string_length(const gearman_vector_st *self)
  196. {
  197. if (not self)
  198. return 0;
  199. return size_t(self->end - self->string);
  200. }
  201. const char *gearman_string_value(const gearman_vector_st *self)
  202. {
  203. if (not self)
  204. return NULL;
  205. return self->string;
  206. }
  207. gearman_string_t gearman_string(const gearman_vector_st *self)
  208. {
  209. assert(self);
  210. gearman_string_t passable= { gearman_string_value(self), gearman_string_length(self) };
  211. return passable;
  212. }
  213. gearman_string_t gearman_string_take_string(gearman_vector_st *self)
  214. {
  215. assert(self);
  216. gearman_string_t passable= gearman_string(self);
  217. _init_string(self);
  218. return passable;
  219. }