1 /*
2 +----------------------------------------------------------------------+
3 | zend_string compatibility layer for PHP 5 & 7 |
4 +----------------------------------------------------------------------+
5 | Copyright (c) 2005-2007 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: Francois Laupretre <francois@tekwire.net> |
16 +----------------------------------------------------------------------+
17 */
18
19 #ifndef _COMPAT_ZEND_STRING_H
20 #define _COMPAT_ZEND_STRING_H
21
22 #ifdef PHP_7
23 /*============================================================================*/
24 #include "zend_string.h"
25
26 #ifndef ZSTR_IS_PERSISTENT
27 # define ZSTR_IS_PERSISTENT(s) (GC_FLAGS(s) & IS_STR_PERSISTENT)
28 #endif
29
30 #else
31 /*============================================================================*/
32 /*---- zend_string for PHP 5 ----*/
33
34 struct _zend_string {
35 int persistent;
36 int hash_is_set; /* needed because computed hash may be null */
37 zend_ulong h; /* hash value */
38 uint32_t refcount;
39 size_t len;
40 char val[1];
41 };
42
43 typedef struct _zend_string zend_string;
44
45 /* Shortcuts */
46
47 #define ZSTR_VAL(zstr) (zstr)->val
48 #define ZSTR_LEN(zstr) (zstr)->len
49 #define ZSTR_H(zstr) (zstr)->h
50 #define ZSTR_HASH(zstr) zend_string_hash_val(zstr)
51
52 #define _ZSTR_HEADER_SIZE XtOffsetOf(zend_string, val)
53 #define _ZSTR_STRUCT_SIZE(len) (_ZSTR_HEADER_SIZE + len + 1)
54
55 #define ZSTR_IS_PERSISTENT(s) (s->persistent)
56
57 /*---------*/
58
zend_string_refcount(zend_string * s)59 static zend_always_inline uint32_t zend_string_refcount(zend_string *s)
60 {
61 return (s->refcount);
62 }
63
64 /*---------*/
65
zend_string_addref(zend_string * s)66 static zend_always_inline uint32_t zend_string_addref(zend_string *s)
67 {
68 return ++(s->refcount);
69 }
70
71 /*---------*/
72
zend_string_delref(zend_string * s)73 static zend_always_inline uint32_t zend_string_delref(zend_string *s)
74 {
75 return --(s->refcount);
76 }
77
78 /*---------*/
79
zend_string_hash_val(zend_string * s)80 static zend_always_inline zend_ulong zend_string_hash_val(zend_string *s)
81 {
82 char c, *p;
83
84 if (! s->hash_is_set) {
85 /* Compute with terminating null but preserve string */
86 p = &(ZSTR_VAL(s)[ZSTR_LEN(s)]);
87 c = (*p);
88 (*p) = '\0';
89 ZSTR_H(s) = zend_get_hash_value(ZSTR_VAL(s), ZSTR_LEN(s)+1);
90 (*p) = c;
91 s->hash_is_set = 1;
92 }
93 return ZSTR_H(s);
94 }
95
96 /*---------*/
97
zend_string_forget_hash_val(zend_string * s)98 static zend_always_inline void zend_string_forget_hash_val(zend_string *s)
99 {
100 s->hash_is_set = 0;
101 ZSTR_H(s) = 0; /* Security */
102 }
103
104 /*---------*/
105
zend_string_alloc(size_t len,int persistent)106 static zend_always_inline zend_string *zend_string_alloc(size_t len, int persistent)
107 {
108 zend_string *ret = (zend_string *)pemalloc(ZEND_MM_ALIGNED_SIZE(_ZSTR_STRUCT_SIZE(len)), persistent);
109 ret->persistent = persistent;
110 zend_string_forget_hash_val(ret);
111 ret->refcount = 1;
112 ZSTR_LEN(ret) = len;
113 return ret;
114 }
115
116 /*---------*/
117
zend_string_safe_alloc(size_t n,size_t m,size_t l,int persistent)118 static zend_always_inline zend_string *zend_string_safe_alloc(size_t n
119 , size_t m, size_t l, int persistent)
120 {
121 zend_string *ret = (zend_string *)safe_pemalloc(n, m, ZEND_MM_ALIGNED_SIZE(_ZSTR_STRUCT_SIZE(l)), persistent);
122 ret->persistent = persistent;
123 zend_string_forget_hash_val(ret);
124 ret->refcount = 1;
125 ZSTR_LEN(ret) = l;
126 return ret;
127 }
128
129 /*---------*/
130
zend_string_init(const char * str,size_t len,int persistent)131 static zend_always_inline zend_string *zend_string_init(const char *str, size_t len, int persistent)
132 {
133 zend_string *ret = zend_string_alloc(len, persistent);
134
135 memcpy(ZSTR_VAL(ret), str, len);
136 ZSTR_VAL(ret)[len] = '\0';
137 return ret;
138 }
139
140 /*---------*/
141
zend_string_dup(zend_string * s,int persistent)142 static zend_always_inline zend_string *zend_string_dup(zend_string *s, int persistent)
143 {
144 zend_string *target;
145
146 target = zend_string_init(ZSTR_VAL(s), ZSTR_LEN(s), persistent);
147 if (s->hash_is_set) {
148 ZSTR_H(target) = ZSTR_H(s);
149 target->hash_is_set = 1;
150 }
151
152 return target;
153 }
154
155 /*---------*/
156
zend_string_realloc(zend_string * s,size_t len,int persistent)157 static zend_always_inline zend_string *zend_string_realloc(zend_string *s
158 , size_t len, int persistent)
159 {
160 zend_string *ret;
161
162 if (EXPECTED(s->refcount == 1)) {
163 ret = (zend_string *)perealloc(s, ZEND_MM_ALIGNED_SIZE(_ZSTR_STRUCT_SIZE(len)), persistent);
164 ZSTR_LEN(ret) = len;
165 zend_string_forget_hash_val(ret);
166 return ret;
167 }
168
169 zend_string_delref(s);
170 ret = zend_string_alloc(len, persistent);
171 memcpy(ZSTR_VAL(ret), ZSTR_VAL(s), MIN(len, ZSTR_LEN(s)) + 1);
172
173 return ret;
174 }
175
176 /*---------*/
177
zend_string_extend(zend_string * s,size_t len,int persistent)178 static zend_always_inline zend_string *zend_string_extend(zend_string *s
179 , size_t len, int persistent)
180 {
181 zend_string *ret;
182
183 ZEND_ASSERT(len >= ZSTR_LEN(s));
184
185 if (EXPECTED(s->refcount == 1)) {
186 ret = (zend_string *)perealloc(s, ZEND_MM_ALIGNED_SIZE(_ZSTR_STRUCT_SIZE(len)), persistent);
187 ZSTR_LEN(ret) = len;
188 zend_string_forget_hash_val(ret);
189 return ret;
190 }
191
192 zend_string_delref(s);
193 ret = zend_string_alloc(len, persistent);
194 memcpy(ZSTR_VAL(ret), ZSTR_VAL(s), ZSTR_LEN(s) + 1);
195
196 return ret;
197 }
198
199 /*---------*/
200
zend_string_truncate(zend_string * s,size_t len,int persistent)201 static zend_always_inline zend_string *zend_string_truncate(zend_string *s
202 , size_t len, int persistent)
203 {
204 zend_string *ret;
205
206 ZEND_ASSERT(len <= ZSTR_LEN(s));
207
208 if (EXPECTED(s->refcount == 1)) {
209 ret = (zend_string *)perealloc(s, ZEND_MM_ALIGNED_SIZE(_ZSTR_STRUCT_SIZE(len)), persistent);
210 ZSTR_LEN(ret) = len;
211 zend_string_forget_hash_val(ret);
212 return ret;
213 }
214
215 zend_string_delref(s);
216 ret = zend_string_alloc(len, persistent);
217 memcpy(ZSTR_VAL(ret), ZSTR_VAL(s), len + 1);
218
219 return ret;
220 }
221
222 /*---------*/
223
zend_string_safe_realloc(zend_string * s,size_t n,size_t m,size_t l,int persistent)224 static zend_always_inline zend_string *zend_string_safe_realloc(zend_string *s
225 , size_t n, size_t m, size_t l, int persistent)
226 {
227 zend_string *ret;
228
229 if (EXPECTED(s->refcount == 1)) {
230 ret = (zend_string *)safe_perealloc(s, n, m, ZEND_MM_ALIGNED_SIZE(_ZSTR_STRUCT_SIZE(l)), persistent);
231 ZSTR_LEN(ret) = (n * m) + l;
232 zend_string_forget_hash_val(ret);
233 return ret;
234 }
235
236 zend_string_delref(s);
237 ret = zend_string_safe_alloc(n, m, l, persistent);
238 memcpy(ZSTR_VAL(ret), ZSTR_VAL(s), MIN((n * m) + l, ZSTR_LEN(s)) + 1);
239 return ret;
240 }
241
242 /*---------*/
243
zend_string_free(zend_string * s)244 static zend_always_inline void zend_string_free(zend_string *s)
245 {
246 if (s) {
247 pefree(s, s->persistent);
248 }
249 }
250
251
252 /*---------*/
253
zend_string_release(zend_string * s)254 static zend_always_inline void zend_string_release(zend_string *s)
255 {
256 if (s) {
257 s->refcount--;
258 if (s->refcount == 0) {
259 zend_string_free(s);
260 }
261 }
262 }
263
264 /*---------*/
265
zend_string_copy(zend_string * s)266 static zend_always_inline zend_string *zend_string_copy(zend_string *s)
267 {
268 zend_string_addref(s);
269 return (s);
270 }
271
272 /*---------*/
273
zend_string_equals(zend_string * s1,zend_string * s2)274 static zend_always_inline zend_bool zend_string_equals(zend_string *s1, zend_string *s2)
275 {
276 return s1 == s2 || (s1->len == s2->len && !memcmp(s1->val, s2->val, s1->len));
277 }
278
279 #define zend_string_equals_literal(str, literal) \
280 ((str)->len == sizeof(literal)-1 && !memcmp((str)->val, literal, sizeof(literal) - 1))
281
282 #endif /* PHP_7 */
283 #endif /* _COMPAT_ZEND_STRING_H */
284