1 /**********************************************************************
2 * $Id$
3 *
4 * Project: MapServer
5 * Purpose: PHP/MapScript extension for MapServer : Utility functions
6 * Header - macros
7 * Author: Daniel Morissette, DM Solutions Group (dmorissette@dmsolutions.ca)
8 *
9 **********************************************************************
10 * Copyright (c) 2000, 2001, Daniel Morissette, DM Solutions Group Inc.
11 *
12 * Permission is hereby granted, free of charge, to any person obtaining a
13 * copy of this software and associated documentation files (the "Software"),
14 * to deal in the Software without restriction, including without limitation
15 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
16 * and/or sell copies of the Software, and to permit persons to whom the
17 * Software is furnished to do so, subject to the following conditions:
18 *
19 * The above copyright notice and this permission notice shall be included in
20 * all copies of this Software or works derived from this Software.
21 *
22 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
25 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
27 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
28 * DEALINGS IN THE SOFTWARE.
29 **********************************************************************/
30
31
32 #ifndef PHP_MAPSCRIPT_UTIL_H
33 #define PHP_MAPSCRIPT_UTIL_H
34
35 #include "php.h"
36 #include "php_globals.h"
37 #include "php_mapscript.h"
38
39 #if PHP_VERSION_ID < 70000
40
41 #if ZEND_MODULE_API_NO < 20010901
42 #define TSRMLS_D void
43 #define TSRMLS_DC
44 #define TSRMLS_C
45 #define TSRMLS_CC
46 #endif
47
48 /* Add pseudo refcount macros for PHP version < 5.3 */
49 #ifndef Z_REFCOUNT_PP
50
51 #define Z_REFCOUNT_PP(ppz) Z_REFCOUNT_P(*(ppz))
52 #define Z_SET_REFCOUNT_PP(ppz, rc) Z_SET_REFCOUNT_P(*(ppz), rc)
53 #define Z_ADDREF_PP(ppz) Z_ADDREF_P(*(ppz))
54 #define Z_DELREF_PP(ppz) Z_DELREF_P(*(ppz))
55 #define Z_ISREF_PP(ppz) Z_ISREF_P(*(ppz))
56 #define Z_SET_ISREF_PP(ppz) Z_SET_ISREF_P(*(ppz))
57 #define Z_UNSET_ISREF_PP(ppz) Z_UNSET_ISREF_P(*(ppz))
58 #define Z_SET_ISREF_TO_PP(ppz, isref) Z_SET_ISREF_TO_P(*(ppz), isref)
59
60 #define Z_REFCOUNT_P(pz) zval_refcount_p(pz)
61 #define Z_SET_REFCOUNT_P(pz, rc) zval_set_refcount_p(pz, rc)
62 #define Z_ADDREF_P(pz) zval_addref_p(pz)
63 #define Z_DELREF_P(pz) zval_delref_p(pz)
64 #define Z_ISREF_P(pz) zval_isref_p(pz)
65 #define Z_SET_ISREF_P(pz) zval_set_isref_p(pz)
66 #define Z_UNSET_ISREF_P(pz) zval_unset_isref_p(pz)
67 #define Z_SET_ISREF_TO_P(pz, isref) zval_set_isref_to_p(pz, isref)
68
69 #define Z_REFCOUNT(z) Z_REFCOUNT_P(&(z))
70 #define Z_SET_REFCOUNT(z, rc) Z_SET_REFCOUNT_P(&(z), rc)
71 #define Z_ADDREF(z) Z_ADDREF_P(&(z))
72 #define Z_DELREF(z) Z_DELREF_P(&(z))
73 #define Z_ISREF(z) Z_ISREF_P(&(z))
74 #define Z_SET_ISREF(z) Z_SET_ISREF_P(&(z))
75 #define Z_UNSET_ISREF(z) Z_UNSET_ISREF_P(&(z))
76 #define Z_SET_ISREF_TO(z, isref) Z_SET_ISREF_TO_P(&(z), isref)
77
78 #if defined(__GNUC__)
79 #define zend_always_inline inline __attribute__((always_inline))
80 #elif defined(_MSC_VER)
81 #define zend_always_inline __forceinline
82 #else
83 #define zend_always_inline inline
84 #endif
85
zval_refcount_p(zval * pz)86 static zend_always_inline zend_uint zval_refcount_p(zval* pz)
87 {
88 return pz->refcount;
89 }
90
zval_set_refcount_p(zval * pz,zend_uint rc)91 static zend_always_inline zend_uint zval_set_refcount_p(zval* pz, zend_uint rc)
92 {
93 return pz->refcount = rc;
94 }
95
zval_addref_p(zval * pz)96 static zend_always_inline zend_uint zval_addref_p(zval* pz)
97 {
98 return ++pz->refcount;
99 }
100
zval_delref_p(zval * pz)101 static zend_always_inline zend_uint zval_delref_p(zval* pz)
102 {
103 return --pz->refcount;
104 }
105
zval_isref_p(zval * pz)106 static zend_always_inline zend_bool zval_isref_p(zval* pz)
107 {
108 return pz->is_ref;
109 }
110
zval_set_isref_p(zval * pz)111 static zend_always_inline zend_bool zval_set_isref_p(zval* pz)
112 {
113 return pz->is_ref = 1;
114 }
115
zval_unset_isref_p(zval * pz)116 static zend_always_inline zend_bool zval_unset_isref_p(zval* pz)
117 {
118 return pz->is_ref = 0;
119 }
120
zval_set_isref_to_p(zval * pz,zend_bool isref)121 static zend_always_inline zend_bool zval_set_isref_to_p(zval* pz, zend_bool isref)
122 {
123 return pz->is_ref = isref;
124 }
125
126 #endif
127
128 /* PHP >=5.3 replaced ZVAL_DELREF by Z_DELREF_P */
129 #if ZEND_MODULE_API_NO >= 20090626
130 #define ZVAL_DELREF Z_DELREF_P
131 #define ZVAL_ADDREF Z_ADDREF_P
132 #endif
133
134
135 #define MAPSCRIPT_REGISTER_CLASS(name, functions, class_entry, constructor) \
136 INIT_CLASS_ENTRY(ce, name, functions); \
137 class_entry = zend_register_internal_class(&ce TSRMLS_CC); \
138 class_entry->create_object = constructor;
139
140 #define MAPSCRIPT_ALLOC_OBJECT(zobj, object_type) \
141 zobj = ecalloc(1, sizeof(object_type));
142
143 #define MAPSCRIPT_FREE_OBJECT(zobj) \
144 zend_hash_destroy(zobj->std.properties); \
145 FREE_HASHTABLE(zobj->std.properties);
146 #endif /* PHP_VERSION_ID < 70000 */
147
148 #if PHP_VERSION_ID >= 70300
149 #define MAPSCRIPT_ADDREF(zv) if(!Z_ISUNDEF(zv)) GC_ADDREF(Z_COUNTED(zv))
150 #define MAPSCRIPT_ADDREF_P(p) if(!Z_ISUNDEF(*p)) GC_ADDREF(Z_COUNTED_P(p))
151 #else
152 #if PHP_VERSION_ID >= 70000
153 #define MAPSCRIPT_ADDREF(zv) if(!(Z_ISUNDEF(zv))) GC_REFCOUNT(Z_COUNTED(zv))++;
154 #define MAPSCRIPT_ADDREF_P(zv) if(!(Z_ISUNDEF(*zv))) GC_REFCOUNT(Z_COUNTED_P(zv))++;
155 #else
156 #define MAPSCRIPT_ADDREF(zobj) if (zobj) Z_ADDREF_P(zobj)
157 #define MAPSCRIPT_ADDREF_P(zv) MAPSCRIPT_ADDREF(zv)
158 #endif /* PHP_VERSION_ID >= 70000 */
159 #endif /* PHP_VERSION_ID >= 70300 */
160
161 #if PHP_VERSION_ID >= 70300
162 #define MAPSCRIPT_DELREF(zv) \
163 if (!(Z_ISUNDEF(zv))) \
164 { \
165 zend_refcounted *_gc = Z_COUNTED(zv); \
166 GC_DELREF(_gc); \
167 if(GC_REFCOUNT(_gc) == 0) \
168 rc_dtor_func(_gc); \
169 ZVAL_UNDEF(&zv); \
170 }
171 #else
172 #if PHP_VERSION_ID >= 70000
173 #if PHP_VERSION_ID >= 70100
174 #define _zval_dtor_func_for_ptr _zval_dtor_func
175 #endif /* PHP_VERSION_ID >= 70100 */
176 #define MAPSCRIPT_DELREF(zv) \
177 if (!(Z_ISUNDEF(zv))) \
178 { \
179 zend_refcounted *_gc = Z_COUNTED_P(&zv); \
180 if(--GC_REFCOUNT(_gc) == 0) \
181 _zval_dtor_func_for_ptr(_gc); \
182 ZVAL_UNDEF(&zv); \
183 }
184 #else
185 #define MAPSCRIPT_DELREF(zobj) \
186 if (zobj) \
187 { \
188 if (Z_REFCOUNT_P(zobj) == 1) { \
189 zval_ptr_dtor(&zobj); \
190 } \
191 else { \
192 Z_DELREF_P(zobj); \
193 } \
194 zobj = NULL; \
195 }
196 #endif /* PHP_VERSION_ID >= 70000 */
197 #endif /* PHP_VERSION_ID >= 70300 */
198
199 #if PHP_VERSION_ID >= 70000
200 #define MAPSCRIPT_FREE_PARENT(parent) \
201 if (parent.child_ptr) \
202 ZVAL_UNDEF(parent.child_ptr); \
203 MAPSCRIPT_DELREF(parent.val);
204
205 #define MAPSCRIPT_MAKE_PARENT(zobj, ptr) \
206 if(zobj == NULL) \
207 ZVAL_UNDEF(&parent.val); \
208 else \
209 ZVAL_COPY_VALUE(&parent.val, zobj); \
210 parent.child_ptr = ptr;
211
212 #define MAPSCRIPT_INIT_PARENT(parent) \
213 ZVAL_UNDEF(&parent.val); \
214 parent.child_ptr = NULL;
215 #else
216
217 #define MAPSCRIPT_FREE_PARENT(parent) \
218 if (parent.child_ptr) \
219 *parent.child_ptr = NULL; \
220 MAPSCRIPT_DELREF(parent.val);
221
222 #define MAPSCRIPT_MAKE_PARENT(zobj, ptr) \
223 parent.val = zobj; \
224 parent.child_ptr = ptr;
225
226 #define MAPSCRIPT_INIT_PARENT(parent) \
227 parent.val = NULL; \
228 parent.child_ptr = NULL;
229 #endif
230
231 #if PHP_VERSION_ID >= 70000
232
233 #define MAPSCRIPT_CALL_METHOD_1(zobj, function_name, retval, arg1) \
234 zend_call_method_with_1_params(&zobj, Z_OBJCE(zobj), NULL, function_name, &retval, arg1);
235
236 #define MAPSCRIPT_CALL_METHOD_2(zobj, function_name, retval, arg1, arg2) \
237 zend_call_method_with_2_params(&zobj, Z_OBJCE(zobj), NULL, function_name, &retval, arg1, arg2);
238
239 #define MAPSCRIPT_CALL_METHOD_2_P(zobj, function_name, retval, arg1, arg2) \
240 zend_call_method_with_2_params(zobj, Z_OBJCE_P(zobj), NULL, function_name, &retval, arg1, arg2);
241
242 #else
243
244 #define MAPSCRIPT_CALL_METHOD_1(zobj, function_name, retval, arg1) \
245 zend_call_method_with_1_params(&zobj, Z_OBJCE_P(zobj), NULL, function_name, &retval, arg1);
246
247 #define MAPSCRIPT_CALL_METHOD_2(zobj, function_name, retval, arg1, arg2) \
248 zend_call_method_with_2_params(&zobj, Z_OBJCE_P(zobj), NULL, function_name, &retval, arg1, arg2);
249
250 #define MAPSCRIPT_CALL_METHOD_2_P(zobj, function_name, retval, arg1, arg2) \
251 MAPSCRIPT_CALL_METHOD_2(zobj, function_name, retval, arg1, arg2)
252
253 #endif /* PHP_VERSION_ID */
254
255 #define STRING_EQUAL(string1, string2) \
256 strcmp(string1, string2) == 0
257
258 /* helpers for getters */
259 #define IF_GET_STRING(property_name, value) \
260 if (strcmp(property, property_name)==0) \
261 { \
262 MAPSCRIPT_RETVAL_STRING( (value ? value:"") , 1); \
263 } \
264
265 #define IF_GET_LONG(property_name, value) \
266 if (strcmp(property, property_name)==0) \
267 { \
268 RETVAL_LONG(value); \
269 } \
270
271 #define IF_GET_DOUBLE(property_name, value) \
272 if (strcmp(property, property_name)==0) \
273 { \
274 RETVAL_DOUBLE(value); \
275 } \
276
277 #if PHP_VERSION_ID >= 70000
278 #define IF_GET_OBJECT(property_name, mapscript_ce, php_object_storage, internal_object) \
279 if (strcmp(property, property_name)==0) \
280 { \
281 if (Z_ISUNDEF(php_object_storage)) { \
282 mapscript_fetch_object(mapscript_ce, zobj, NULL, (void*)internal_object, \
283 &php_object_storage TSRMLS_CC); \
284 } \
285 RETURN_ZVAL(&php_object_storage, 1, 0); \
286 }
287 #else
288 #define IF_GET_OBJECT(property_name, mapscript_ce, php_object_storage, internal_object) \
289 if (strcmp(property, property_name)==0) \
290 { \
291 if (!php_object_storage) { \
292 mapscript_fetch_object(mapscript_ce, zobj, NULL, (void*)internal_object, \
293 &php_object_storage TSRMLS_CC); \
294 } \
295 RETURN_ZVAL(php_object_storage, 1, 0); \
296 }
297 #endif
298
299 #if PHP_VERSION_ID >= 70000
300 #define CHECK_OBJECT(mapscript_ce, php_object_storage, internal_object) \
301 if (Z_ISUNDEF(php_object_storage)) { \
302 mapscript_fetch_object(mapscript_ce, zobj, NULL, (void*)internal_object, \
303 &php_object_storage TSRMLS_CC); \
304 }
305 #else
306 #define CHECK_OBJECT(mapscript_ce, php_object_storage, internal_object) \
307 if (!php_object_storage) { \
308 mapscript_fetch_object(mapscript_ce, zobj, NULL, (void*)internal_object, \
309 &php_object_storage TSRMLS_CC); \
310 }
311 #endif
312
313 /* helpers for setters */
314 #define IF_SET_STRING(property_name, internal, value) \
315 if (strcmp(property, property_name)==0) \
316 { \
317 convert_to_string(value); \
318 if (internal) free(internal); \
319 if (Z_STRVAL_P(value)) \
320 internal = msStrdup(Z_STRVAL_P(value)); \
321 }
322
323 #define IF_SET_LONG(property_name, internal, value) \
324 if (strcmp(property, property_name)==0) \
325 { \
326 convert_to_long(value); \
327 internal = Z_LVAL_P(value); \
328 }
329
330 #define IF_SET_DOUBLE(property_name, internal, value) \
331 if (strcmp(property, property_name)==0) \
332 { \
333 convert_to_double(value); \
334 internal = Z_DVAL_P(value); \
335 }
336
337 #define IF_SET_BYTE(property_name, internal, value) \
338 if (strcmp(property, property_name)==0) \
339 { \
340 convert_to_long(value); \
341 internal = (unsigned char)Z_LVAL_P(value); \
342 }
343
344 #define IF_SET_COLOR(property_name, internal, value) \
345 if (strcmp(property, property_name)==0) \
346 { \
347 convert_to_long(value); \
348 /* validate the color value */ \
349 if (Z_LVAL_P(value) < 0 || Z_LVAL_P(value) > 255) { \
350 mapscript_throw_exception("Invalid color value. It must be between 0 and 255." TSRMLS_CC); \
351 return; \
352 } \
353 internal = Z_LVAL_P(value); \
354 }
355
356 #if PHP_VERSION_ID < 70000
357 zend_object_value mapscript_object_new(zend_object *zobj,
358 zend_class_entry *ce,
359 void (*zend_objects_free_object) TSRMLS_DC);
360 #endif /* PHP_VERSION_ID < 70000 */
361
362 int mapscript_extract_associative_array(HashTable *php, char **array);
363
364 #endif /* PHP_MAPSCRIPT_UTIL_H */
365