xref: /PHP-7.1/ext/standard/php_smart_string.h (revision ccd4716e)
1 /*
2    +----------------------------------------------------------------------+
3    | PHP Version 7                                                        |
4    +----------------------------------------------------------------------+
5    | Copyright (c) 1997-2018 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    |         Xinchen Hui <laruence@php.net>                               |
17    +----------------------------------------------------------------------+
18  */
19 
20 /* $Id$ */
21 
22 #ifndef PHP_SMART_STRING_H
23 #define PHP_SMART_STRING_H
24 
25 #include "php_smart_string_public.h"
26 
27 #include <stdlib.h>
28 #ifndef SMART_STR_USE_REALLOC
29 #include <zend.h>
30 #endif
31 
32 #define smart_string_0(x) do {										\
33 	if ((x)->c) {													\
34 		(x)->c[(x)->len] = '\0';									\
35 	}																\
36 } while (0)
37 
38 #ifndef SMART_STRING_PREALLOC
39 #define SMART_STRING_PREALLOC 128
40 #endif
41 
42 #ifndef SMART_STRING_START_SIZE
43 #define SMART_STRING_START_SIZE 78
44 #endif
45 
46 #ifdef SMART_STRING_USE_REALLOC
47 #define SMART_STRING_REALLOC(a,b,c) realloc((a),(b))
48 #else
49 #define SMART_STRING_REALLOC(a,b,c) perealloc((a),(b),(c))
50 #endif
51 
52 #define SMART_STRING_DO_REALLOC(d, what) \
53 	(d)->c = (char *) SMART_STRING_REALLOC((d)->c, (d)->a + 1, (what))
54 
55 #define smart_string_alloc4(d, n, what, newlen) do {				\
56 	if (!(d)->c) {													\
57 		(d)->len = 0;												\
58 		newlen = (n);												\
59 		(d)->a = newlen < SMART_STRING_START_SIZE 					\
60 				? SMART_STRING_START_SIZE 							\
61 				: newlen + SMART_STRING_PREALLOC;					\
62 		SMART_STRING_DO_REALLOC(d, what);							\
63 	} else {														\
64 		if(UNEXPECTED((size_t)n > SIZE_MAX - (d)->len)) {					\
65 			zend_error(E_ERROR, "String size overflow");			\
66 		}															\
67 		newlen = (d)->len + (n);									\
68 		if (newlen >= (d)->a) {										\
69 			(d)->a = newlen + SMART_STRING_PREALLOC;				\
70 			SMART_STRING_DO_REALLOC(d, what);						\
71 		}															\
72 	}																\
73 } while (0)
74 
75 #define smart_string_alloc(d, n, what) \
76 	smart_string_alloc4((d), (n), (what), newlen)
77 
78 /* wrapper */
79 
80 #define smart_string_appends_ex(dest, src, what) \
81 	smart_string_appendl_ex((dest), (src), strlen(src), (what))
82 #define smart_string_appends(dest, src) \
83 	smart_string_appendl((dest), (src), strlen(src))
84 
85 #define smart_string_appendc(dest, c) \
86 	smart_string_appendc_ex((dest), (c), 0)
87 #define smart_string_free(s) \
88 	smart_string_free_ex((s), 0)
89 #define smart_string_appendl(dest, src, len) \
90 	smart_string_appendl_ex((dest), (src), (len), 0)
91 #define smart_string_append(dest, src) \
92 	smart_string_append_ex((dest), (src), 0)
93 #define smart_string_append_long(dest, val) \
94 	smart_string_append_long_ex((dest), (val), 0)
95 #define smart_string_append_unsigned(dest, val) \
96 	smart_string_append_unsigned_ex((dest), (val), 0)
97 
98 #define smart_string_appendc_ex(dest, ch, what) do {					\
99 	size_t __nl;													\
100 	smart_string_alloc4((dest), 1, (what), __nl);						\
101 	(dest)->len = __nl;												\
102 	((unsigned char *) (dest)->c)[(dest)->len - 1] = (ch);			\
103 } while (0)
104 
105 #define smart_string_free_ex(s, what) do {								\
106 	smart_string *__s = (smart_string *) (s);								\
107 	if (__s->c) {													\
108 		pefree(__s->c, what);										\
109 		__s->c = NULL;												\
110 	}																\
111 	__s->a = __s->len = 0;											\
112 } while (0)
113 
114 #define smart_string_appendl_ex(dest, src, nlen, what) do {			\
115 	size_t __nl;													\
116 	smart_string *__dest = (smart_string *) (dest);						\
117 																	\
118 	smart_string_alloc4(__dest, (nlen), (what), __nl);					\
119 	memcpy(__dest->c + __dest->len, (src), (nlen));					\
120 	__dest->len = __nl;												\
121 } while (0)
122 
123 #define smart_string_append_generic_ex(dest, num, type, vartype, func) do {	\
124 	char __b[32];															\
125 	char *__t = zend_print##func##_to_buf(__b + sizeof(__b) - 1, (num));	\
126 	smart_string_appendl_ex((dest), __t, __b + sizeof(__b) - 1 - __t, (type));	\
127 } while (0)
128 
129 #define smart_string_append_unsigned_ex(dest, num, type) \
130 	smart_string_append_generic_ex((dest), (num), (type), zend_ulong, _ulong)
131 
132 #define smart_string_append_long_ex(dest, num, type) \
133 	smart_string_append_generic_ex((dest), (num), (type), zend_ulong, _long)
134 
135 #define smart_string_append_ex(dest, src, what) \
136 	smart_string_appendl_ex((dest), ((smart_string *)(src))->c, \
137 		((smart_string *)(src))->len, (what));
138 
139 
140 #define smart_string_setl(dest, src, nlen) do {						\
141 	(dest)->len = (nlen);											\
142 	(dest)->a = (nlen) + 1;											\
143 	(dest)->c = (char *) (src);										\
144 } while (0)
145 
146 #define smart_string_sets(dest, src) \
147 	smart_string_setl((dest), (src), strlen(src));
148 
149 #endif
150