php_smart_str.h 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199
  1. /*
  2. +----------------------------------------------------------------------+
  3. | PHP Version 5 |
  4. +----------------------------------------------------------------------+
  5. | Copyright (c) 1997-2016 The PHP Group |
  6. +----------------------------------------------------------------------+
  7. | This source file is subject to version 3.01 of the PHP license, |
  8. | that is bundled with this package in the file LICENSE, and is |
  9. | available through the world-wide-web at the following url: |
  10. | http://www.php.net/license/3_01.txt |
  11. | If you did not receive a copy of the PHP license and are unable to |
  12. | obtain it through the world-wide-web, please send a note to |
  13. | license@php.net so we can mail you a copy immediately. |
  14. +----------------------------------------------------------------------+
  15. | Author: Sascha Schumann <sascha@schumann.cx> |
  16. +----------------------------------------------------------------------+
  17. */
  18. /* $Id$ */
  19. #ifndef PHP_SMART_STR_H
  20. #define PHP_SMART_STR_H
  21. #include "php_smart_str_public.h"
  22. #include <stdlib.h>
  23. #ifndef SMART_STR_USE_REALLOC
  24. #include <zend.h>
  25. #endif
  26. #define smart_str_0(x) do { \
  27. if ((x)->c) { \
  28. (x)->c[(x)->len] = '\0'; \
  29. } \
  30. } while (0)
  31. #ifndef SMART_STR_PREALLOC
  32. #define SMART_STR_PREALLOC 128
  33. #endif
  34. #ifndef SMART_STR_START_SIZE
  35. #define SMART_STR_START_SIZE 78
  36. #endif
  37. #ifdef SMART_STR_USE_REALLOC
  38. #define SMART_STR_REALLOC(a,b,c) realloc((a),(b))
  39. #else
  40. #define SMART_STR_REALLOC(a,b,c) perealloc((a),(b),(c))
  41. #endif
  42. #define SMART_STR_DO_REALLOC(d, what) \
  43. (d)->c = SMART_STR_REALLOC((d)->c, (d)->a + 1, (what))
  44. #define smart_str_alloc4(d, n, what, newlen) do { \
  45. if (!(d)->c) { \
  46. (d)->len = 0; \
  47. newlen = (n); \
  48. (d)->a = newlen < SMART_STR_START_SIZE \
  49. ? SMART_STR_START_SIZE \
  50. : (newlen >= (INT_MAX - SMART_STR_PREALLOC)? newlen \
  51. : (newlen + SMART_STR_PREALLOC)); \
  52. SMART_STR_DO_REALLOC(d, what); \
  53. } else { \
  54. newlen = (d)->len + (n); \
  55. if (newlen >= (d)->a) { \
  56. (d)->a = newlen + SMART_STR_PREALLOC; \
  57. if (UNEXPECTED((d)->a >= INT_MAX)) { \
  58. zend_error(E_ERROR, "String size overflow"); \
  59. } \
  60. SMART_STR_DO_REALLOC(d, what); \
  61. } \
  62. } \
  63. } while (0)
  64. #define smart_str_alloc(d, n, what) \
  65. smart_str_alloc4((d), (n), (what), newlen)
  66. /* wrapper */
  67. #define smart_str_appends_ex(dest, src, what) \
  68. smart_str_appendl_ex((dest), (src), strlen(src), (what))
  69. #define smart_str_appends(dest, src) \
  70. smart_str_appendl((dest), (src), strlen(src))
  71. #define smart_str_appendc(dest, c) \
  72. smart_str_appendc_ex((dest), (c), 0)
  73. #define smart_str_free(s) \
  74. smart_str_free_ex((s), 0)
  75. #define smart_str_appendl(dest, src, len) \
  76. smart_str_appendl_ex((dest), (src), (len), 0)
  77. #define smart_str_append(dest, src) \
  78. smart_str_append_ex((dest), (src), 0)
  79. #define smart_str_append_long(dest, val) \
  80. smart_str_append_long_ex((dest), (val), 0)
  81. #define smart_str_append_off_t(dest, val) \
  82. smart_str_append_off_t_ex((dest), (val), 0)
  83. #define smart_str_append_unsigned(dest, val) \
  84. smart_str_append_unsigned_ex((dest), (val), 0)
  85. #define smart_str_appendc_ex(dest, ch, what) do { \
  86. register size_t __nl; \
  87. smart_str_alloc4((dest), 1, (what), __nl); \
  88. (dest)->len = __nl; \
  89. ((unsigned char *) (dest)->c)[(dest)->len - 1] = (ch); \
  90. } while (0)
  91. #define smart_str_free_ex(s, what) do { \
  92. smart_str *__s = (smart_str *) (s); \
  93. if (__s->c) { \
  94. pefree(__s->c, what); \
  95. __s->c = NULL; \
  96. } \
  97. __s->a = __s->len = 0; \
  98. } while (0)
  99. #define smart_str_appendl_ex(dest, src, nlen, what) do { \
  100. register size_t __nl; \
  101. smart_str *__dest = (smart_str *) (dest); \
  102. \
  103. smart_str_alloc4(__dest, (nlen), (what), __nl); \
  104. memcpy(__dest->c + __dest->len, (src), (nlen)); \
  105. __dest->len = __nl; \
  106. } while (0)
  107. /* input: buf points to the END of the buffer */
  108. #define smart_str_print_unsigned4(buf, num, vartype, result) do { \
  109. char *__p = (buf); \
  110. vartype __num = (num); \
  111. *__p = '\0'; \
  112. do { \
  113. *--__p = (char) (__num % 10) + '0'; \
  114. __num /= 10; \
  115. } while (__num > 0); \
  116. result = __p; \
  117. } while (0)
  118. /* buf points to the END of the buffer */
  119. #define smart_str_print_long4(buf, num, vartype, result) do { \
  120. if (num < 0) { \
  121. /* this might cause problems when dealing with LONG_MIN \
  122. and machines which don't support long long. Works \
  123. flawlessly on 32bit x86 */ \
  124. smart_str_print_unsigned4((buf), -(num), vartype, (result)); \
  125. *--(result) = '-'; \
  126. } else { \
  127. smart_str_print_unsigned4((buf), (num), vartype, (result)); \
  128. } \
  129. } while (0)
  130. /*
  131. * these could be replaced using a braced-group inside an expression
  132. * for GCC compatible compilers, e.g.
  133. *
  134. * #define f(..) ({char *r;..;__r;})
  135. */
  136. static inline char *smart_str_print_long(char *buf, long num) {
  137. char *r;
  138. smart_str_print_long4(buf, num, unsigned long, r);
  139. return r;
  140. }
  141. static inline char *smart_str_print_unsigned(char *buf, long num) {
  142. char *r;
  143. smart_str_print_unsigned4(buf, num, unsigned long, r);
  144. return r;
  145. }
  146. #define smart_str_append_generic_ex(dest, num, type, vartype, func) do { \
  147. char __b[32]; \
  148. char *__t; \
  149. smart_str_print##func##4 (__b + sizeof(__b) - 1, (num), vartype, __t); \
  150. smart_str_appendl_ex((dest), __t, __b + sizeof(__b) - 1 - __t, (type)); \
  151. } while (0)
  152. #define smart_str_append_unsigned_ex(dest, num, type) \
  153. smart_str_append_generic_ex((dest), (num), (type), unsigned long, _unsigned)
  154. #define smart_str_append_long_ex(dest, num, type) \
  155. smart_str_append_generic_ex((dest), (num), (type), unsigned long, _long)
  156. #define smart_str_append_off_t_ex(dest, num, type) \
  157. smart_str_append_generic_ex((dest), (num), (type), off_t, _long)
  158. #define smart_str_append_ex(dest, src, what) \
  159. smart_str_appendl_ex((dest), ((smart_str *)(src))->c, \
  160. ((smart_str *)(src))->len, (what));
  161. #define smart_str_setl(dest, src, nlen) do { \
  162. (dest)->len = (nlen); \
  163. (dest)->a = (nlen) + 1; \
  164. (dest)->c = (char *) (src); \
  165. } while (0)
  166. #define smart_str_sets(dest, src) \
  167. smart_str_setl((dest), (src), strlen(src));
  168. #endif