zend_smart_str.h 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155
  1. /*
  2. +----------------------------------------------------------------------+
  3. | Copyright (c) The PHP Group |
  4. +----------------------------------------------------------------------+
  5. | This source file is subject to version 3.01 of the PHP license, |
  6. | that is bundled with this package in the file LICENSE, and is |
  7. | available through the world-wide-web at the following url: |
  8. | https://www.php.net/license/3_01.txt |
  9. | If you did not receive a copy of the PHP license and are unable to |
  10. | obtain it through the world-wide-web, please send a note to |
  11. | license@php.net so we can mail you a copy immediately. |
  12. +----------------------------------------------------------------------+
  13. | Author: Sascha Schumann <sascha@schumann.cx> |
  14. +----------------------------------------------------------------------+
  15. */
  16. #ifndef ZEND_SMART_STR_H
  17. #define ZEND_SMART_STR_H
  18. #include <zend.h>
  19. #include "zend_globals.h"
  20. #include "zend_smart_str_public.h"
  21. #define smart_str_appends_ex(dest, src, what) \
  22. smart_str_appendl_ex((dest), (src), strlen(src), (what))
  23. #define smart_str_appends(dest, src) \
  24. smart_str_appendl((dest), (src), strlen(src))
  25. #define smart_str_extend(dest, len) \
  26. smart_str_extend_ex((dest), (len), 0)
  27. #define smart_str_appendc(dest, c) \
  28. smart_str_appendc_ex((dest), (c), 0)
  29. #define smart_str_appendl(dest, src, len) \
  30. smart_str_appendl_ex((dest), (src), (len), 0)
  31. #define smart_str_append(dest, src) \
  32. smart_str_append_ex((dest), (src), 0)
  33. #define smart_str_append_smart_str(dest, src) \
  34. smart_str_append_smart_str_ex((dest), (src), 0)
  35. #define smart_str_sets(dest, src) \
  36. smart_str_setl((dest), (src), strlen(src));
  37. #define smart_str_append_long(dest, val) \
  38. smart_str_append_long_ex((dest), (val), 0)
  39. #define smart_str_append_unsigned(dest, val) \
  40. smart_str_append_unsigned_ex((dest), (val), 0)
  41. #define smart_str_free(dest) \
  42. smart_str_free_ex((dest), 0)
  43. BEGIN_EXTERN_C()
  44. ZEND_API void ZEND_FASTCALL smart_str_erealloc(smart_str *str, size_t len);
  45. ZEND_API void ZEND_FASTCALL smart_str_realloc(smart_str *str, size_t len);
  46. ZEND_API void ZEND_FASTCALL smart_str_append_escaped(smart_str *str, const char *s, size_t l);
  47. /* If zero_fraction is true, then a ".0" will be added to numbers that would not otherwise
  48. * have a fractional part and look like integers. */
  49. ZEND_API void ZEND_FASTCALL smart_str_append_double(
  50. smart_str *str, double num, int precision, bool zero_fraction);
  51. ZEND_API void smart_str_append_printf(smart_str *dest, const char *format, ...)
  52. ZEND_ATTRIBUTE_FORMAT(printf, 2, 3);
  53. ZEND_API void ZEND_FASTCALL smart_str_append_escaped_truncated(smart_str *str, zend_string *value, size_t length);
  54. ZEND_API void ZEND_FASTCALL smart_str_append_scalar(smart_str *str, zval *value, size_t truncate);
  55. END_EXTERN_C()
  56. static zend_always_inline size_t smart_str_alloc(smart_str *str, size_t len, bool persistent) {
  57. if (UNEXPECTED(!str->s)) {
  58. goto do_smart_str_realloc;
  59. } else {
  60. len += ZSTR_LEN(str->s);
  61. if (UNEXPECTED(len >= str->a)) {
  62. do_smart_str_realloc:
  63. if (persistent) {
  64. smart_str_realloc(str, len);
  65. } else {
  66. smart_str_erealloc(str, len);
  67. }
  68. }
  69. }
  70. return len;
  71. }
  72. static zend_always_inline char* smart_str_extend_ex(smart_str *dest, size_t len, bool persistent) {
  73. size_t new_len = smart_str_alloc(dest, len, persistent);
  74. char *ret = ZSTR_VAL(dest->s) + ZSTR_LEN(dest->s);
  75. ZSTR_LEN(dest->s) = new_len;
  76. return ret;
  77. }
  78. static zend_always_inline void smart_str_free_ex(smart_str *str, bool persistent) {
  79. if (str->s) {
  80. zend_string_release_ex(str->s, persistent);
  81. str->s = NULL;
  82. }
  83. str->a = 0;
  84. }
  85. static zend_always_inline void smart_str_0(smart_str *str) {
  86. if (str->s) {
  87. ZSTR_VAL(str->s)[ZSTR_LEN(str->s)] = '\0';
  88. }
  89. }
  90. static zend_always_inline size_t smart_str_get_len(smart_str *str) {
  91. return str->s ? ZSTR_LEN(str->s) : 0;
  92. }
  93. static zend_always_inline zend_string *smart_str_extract(smart_str *str) {
  94. if (str->s) {
  95. zend_string *res;
  96. smart_str_0(str);
  97. res = str->s;
  98. str->s = NULL;
  99. return res;
  100. } else {
  101. return ZSTR_EMPTY_ALLOC();
  102. }
  103. }
  104. static zend_always_inline void smart_str_appendc_ex(smart_str *dest, char ch, bool persistent) {
  105. size_t new_len = smart_str_alloc(dest, 1, persistent);
  106. ZSTR_VAL(dest->s)[new_len - 1] = ch;
  107. ZSTR_LEN(dest->s) = new_len;
  108. }
  109. static zend_always_inline void smart_str_appendl_ex(smart_str *dest, const char *str, size_t len, bool persistent) {
  110. size_t new_len = smart_str_alloc(dest, len, persistent);
  111. memcpy(ZSTR_VAL(dest->s) + ZSTR_LEN(dest->s), str, len);
  112. ZSTR_LEN(dest->s) = new_len;
  113. }
  114. static zend_always_inline void smart_str_append_ex(smart_str *dest, const zend_string *src, bool persistent) {
  115. smart_str_appendl_ex(dest, ZSTR_VAL(src), ZSTR_LEN(src), persistent);
  116. }
  117. static zend_always_inline void smart_str_append_smart_str_ex(smart_str *dest, const smart_str *src, bool persistent) {
  118. if (src->s && ZSTR_LEN(src->s)) {
  119. smart_str_append_ex(dest, src->s, persistent);
  120. }
  121. }
  122. static zend_always_inline void smart_str_append_long_ex(smart_str *dest, zend_long num, bool persistent) {
  123. char buf[32];
  124. char *result = zend_print_long_to_buf(buf + sizeof(buf) - 1, num);
  125. smart_str_appendl_ex(dest, result, buf + sizeof(buf) - 1 - result, persistent);
  126. }
  127. static zend_always_inline void smart_str_append_unsigned_ex(smart_str *dest, zend_ulong num, bool persistent) {
  128. char buf[32];
  129. char *result = zend_print_ulong_to_buf(buf + sizeof(buf) - 1, num);
  130. smart_str_appendl_ex(dest, result, buf + sizeof(buf) - 1 - result, persistent);
  131. }
  132. static zend_always_inline void smart_str_setl(smart_str *dest, const char *src, size_t len) {
  133. smart_str_free(dest);
  134. smart_str_appendl(dest, src, len);
  135. }
  136. #endif