1 | /* |
2 | +----------------------------------------------------------------------+ |
3 | | PHP Version 5 | |
4 | +----------------------------------------------------------------------+ |
5 | | Copyright (c) 1997-2015 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 | |
19 | /* $Id$ */ |
20 | |
21 | #ifndef PHP_SMART_STR_H |
22 | #define PHP_SMART_STR_H |
23 | |
24 | #include "php_smart_str_public.h" |
25 | |
26 | #include <stdlib.h> |
27 | #ifndef SMART_STR_USE_REALLOC |
28 | #include <zend.h> |
29 | #endif |
30 | |
31 | #define smart_str_0(x) do { \ |
32 | if ((x)->c) { \ |
33 | (x)->c[(x)->len] = '\0'; \ |
34 | } \ |
35 | } while (0) |
36 | |
37 | #ifndef SMART_STR_PREALLOC |
38 | #define SMART_STR_PREALLOC 128 |
39 | #endif |
40 | |
41 | #ifndef SMART_STR_START_SIZE |
42 | #define SMART_STR_START_SIZE 78 |
43 | #endif |
44 | |
45 | #ifdef SMART_STR_USE_REALLOC |
46 | #define SMART_STR_REALLOC(a,b,c) realloc((a),(b)) |
47 | #else |
48 | #define SMART_STR_REALLOC(a,b,c) perealloc((a),(b),(c)) |
49 | #endif |
50 | |
51 | #define SMART_STR_DO_REALLOC(d, what) \ |
52 | (d)->c = SMART_STR_REALLOC((d)->c, (d)->a + 1, (what)) |
53 | |
54 | #define smart_str_alloc4(d, n, what, newlen) do { \ |
55 | if (!(d)->c) { \ |
56 | (d)->len = 0; \ |
57 | newlen = (n); \ |
58 | (d)->a = newlen < SMART_STR_START_SIZE \ |
59 | ? SMART_STR_START_SIZE \ |
60 | : newlen + SMART_STR_PREALLOC; \ |
61 | SMART_STR_DO_REALLOC(d, what); \ |
62 | } else { \ |
63 | newlen = (d)->len + (n); \ |
64 | if (newlen >= (d)->a) { \ |
65 | (d)->a = newlen + SMART_STR_PREALLOC; \ |
66 | SMART_STR_DO_REALLOC(d, what); \ |
67 | } \ |
68 | } \ |
69 | } while (0) |
70 | |
71 | #define smart_str_alloc(d, n, what) \ |
72 | smart_str_alloc4((d), (n), (what), newlen) |
73 | |
74 | /* wrapper */ |
75 | |
76 | #define smart_str_appends_ex(dest, src, what) \ |
77 | smart_str_appendl_ex((dest), (src), strlen(src), (what)) |
78 | #define smart_str_appends(dest, src) \ |
79 | smart_str_appendl((dest), (src), strlen(src)) |
80 | |
81 | #define smart_str_appendc(dest, c) \ |
82 | smart_str_appendc_ex((dest), (c), 0) |
83 | #define smart_str_free(s) \ |
84 | smart_str_free_ex((s), 0) |
85 | #define smart_str_appendl(dest, src, len) \ |
86 | smart_str_appendl_ex((dest), (src), (len), 0) |
87 | #define smart_str_append(dest, src) \ |
88 | smart_str_append_ex((dest), (src), 0) |
89 | #define smart_str_append_long(dest, val) \ |
90 | smart_str_append_long_ex((dest), (val), 0) |
91 | #define smart_str_append_off_t(dest, val) \ |
92 | smart_str_append_off_t_ex((dest), (val), 0) |
93 | #define smart_str_append_unsigned(dest, val) \ |
94 | smart_str_append_unsigned_ex((dest), (val), 0) |
95 | |
96 | #define smart_str_appendc_ex(dest, ch, what) do { \ |
97 | register size_t __nl; \ |
98 | smart_str_alloc4((dest), 1, (what), __nl); \ |
99 | (dest)->len = __nl; \ |
100 | ((unsigned char *) (dest)->c)[(dest)->len - 1] = (ch); \ |
101 | } while (0) |
102 | |
103 | #define smart_str_free_ex(s, what) do { \ |
104 | smart_str *__s = (smart_str *) (s); \ |
105 | if (__s->c) { \ |
106 | pefree(__s->c, what); \ |
107 | __s->c = NULL; \ |
108 | } \ |
109 | __s->a = __s->len = 0; \ |
110 | } while (0) |
111 | |
112 | #define smart_str_appendl_ex(dest, src, nlen, what) do { \ |
113 | register size_t __nl; \ |
114 | smart_str *__dest = (smart_str *) (dest); \ |
115 | \ |
116 | smart_str_alloc4(__dest, (nlen), (what), __nl); \ |
117 | memcpy(__dest->c + __dest->len, (src), (nlen)); \ |
118 | __dest->len = __nl; \ |
119 | } while (0) |
120 | |
121 | /* input: buf points to the END of the buffer */ |
122 | #define smart_str_print_unsigned4(buf, num, vartype, result) do { \ |
123 | char *__p = (buf); \ |
124 | vartype __num = (num); \ |
125 | *__p = '\0'; \ |
126 | do { \ |
127 | *--__p = (char) (__num % 10) + '0'; \ |
128 | __num /= 10; \ |
129 | } while (__num > 0); \ |
130 | result = __p; \ |
131 | } while (0) |
132 | |
133 | /* buf points to the END of the buffer */ |
134 | #define smart_str_print_long4(buf, num, vartype, result) do { \ |
135 | if (num < 0) { \ |
136 | /* this might cause problems when dealing with LONG_MIN \ |
137 | and machines which don't support long long. Works \ |
138 | flawlessly on 32bit x86 */ \ |
139 | smart_str_print_unsigned4((buf), -(num), vartype, (result)); \ |
140 | *--(result) = '-'; \ |
141 | } else { \ |
142 | smart_str_print_unsigned4((buf), (num), vartype, (result)); \ |
143 | } \ |
144 | } while (0) |
145 | |
146 | /* |
147 | * these could be replaced using a braced-group inside an expression |
148 | * for GCC compatible compilers, e.g. |
149 | * |
150 | * #define f(..) ({char *r;..;__r;}) |
151 | */ |
152 | |
153 | static inline char *smart_str_print_long(char *buf, long num) { |
154 | char *r; |
155 | smart_str_print_long4(buf, num, unsigned long, r); |
156 | return r; |
157 | } |
158 | |
159 | static inline char *smart_str_print_unsigned(char *buf, long num) { |
160 | char *r; |
161 | smart_str_print_unsigned4(buf, num, unsigned long, r); |
162 | return r; |
163 | } |
164 | |
165 | #define smart_str_append_generic_ex(dest, num, type, vartype, func) do { \ |
166 | char __b[32]; \ |
167 | char *__t; \ |
168 | smart_str_print##func##4 (__b + sizeof(__b) - 1, (num), vartype, __t); \ |
169 | smart_str_appendl_ex((dest), __t, __b + sizeof(__b) - 1 - __t, (type)); \ |
170 | } while (0) |
171 | |
172 | #define smart_str_append_unsigned_ex(dest, num, type) \ |
173 | smart_str_append_generic_ex((dest), (num), (type), unsigned long, _unsigned) |
174 | |
175 | #define smart_str_append_long_ex(dest, num, type) \ |
176 | smart_str_append_generic_ex((dest), (num), (type), unsigned long, _long) |
177 | |
178 | #define smart_str_append_off_t_ex(dest, num, type) \ |
179 | smart_str_append_generic_ex((dest), (num), (type), off_t, _long) |
180 | |
181 | #define smart_str_append_ex(dest, src, what) \ |
182 | smart_str_appendl_ex((dest), ((smart_str *)(src))->c, \ |
183 | ((smart_str *)(src))->len, (what)); |
184 | |
185 | |
186 | #define smart_str_setl(dest, src, nlen) do { \ |
187 | (dest)->len = (nlen); \ |
188 | (dest)->a = (nlen) + 1; \ |
189 | (dest)->c = (char *) (src); \ |
190 | } while (0) |
191 | |
192 | #define smart_str_sets(dest, src) \ |
193 | smart_str_setl((dest), (src), strlen(src)); |
194 | |
195 | #endif |
196 | |