2 +----------------------------------------------------------------------+
4 +----------------------------------------------------------------------+
5 | Copyright (c) 1998-2013 Zend Technologies Ltd. (http://www.zend.com) |
6 +----------------------------------------------------------------------+
7 | This source file is subject to version 2.00 of the Zend 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.zend.com/license/2_00.txt. |
11 | If you did not receive a copy of the Zend license and are unable to |
12 | obtain it through the world-wide-web, please send a note to |
13 | license@zend.com so we can mail you a copy immediately. |
14 +----------------------------------------------------------------------+
15 | Authors: Andi Gutmans <andi@zend.com> |
16 | Zeev Suraski <zeev@zend.com> |
17 +----------------------------------------------------------------------+
25 #include "zend_list.h"
27 #include "zend_globals.h"
29 ZEND_API
int le_index_ptr
;
32 static HashTable list_destructors
;
35 ZEND_API
int zend_list_insert(void *ptr
, int type TSRMLS_DC
)
38 zend_rsrc_list_entry le
;
44 index
= zend_hash_next_free_element(&EG(regular_list
));
46 zend_hash_index_update(&EG(regular_list
), index
, (void *) &le
, sizeof(zend_rsrc_list_entry
), NULL
);
50 ZEND_API
int _zend_list_delete(int id TSRMLS_DC
)
52 zend_rsrc_list_entry
*le
;
54 if (zend_hash_index_find(&EG(regular_list
), id
, (void **) &le
)==SUCCESS
) {
55 /* printf("del(%d): %d->%d\n", id, le->refcount, le->refcount-1); */
56 if (--le
->refcount
<=0) {
57 return zend_hash_index_del(&EG(regular_list
), id
);
67 ZEND_API
void *_zend_list_find(int id
, int *type TSRMLS_DC
)
69 zend_rsrc_list_entry
*le
;
71 if (zend_hash_index_find(&EG(regular_list
), id
, (void **) &le
)==SUCCESS
) {
80 ZEND_API
int _zend_list_addref(int id TSRMLS_DC
)
82 zend_rsrc_list_entry
*le
;
84 if (zend_hash_index_find(&EG(regular_list
), id
, (void **) &le
)==SUCCESS
) {
85 /* printf("add(%d): %d->%d\n", id, le->refcount, le->refcount+1); */
94 ZEND_API
int zend_register_resource(zval
*rsrc_result
, void *rsrc_pointer
, int rsrc_type TSRMLS_DC
)
98 rsrc_id
= zend_list_insert(rsrc_pointer
, rsrc_type TSRMLS_CC
);
101 rsrc_result
->value
.lval
= rsrc_id
;
102 rsrc_result
->type
= IS_RESOURCE
;
109 ZEND_API
void *zend_fetch_resource(zval
**passed_id TSRMLS_DC
, int default_id
, const char *resource_type_name
, int *found_resource_type
, int num_resource_types
, ...)
112 int actual_resource_type
;
114 va_list resource_types
;
117 const char *class_name
;
119 if (default_id
==-1) { /* use id */
121 if (resource_type_name
) {
122 class_name
= get_active_class_name(&space TSRMLS_CC
);
123 zend_error(E_WARNING
, "%s%s%s(): no %s resource supplied", class_name
, space
, get_active_function_name(TSRMLS_C
), resource_type_name
);
126 } else if ((*passed_id
)->type
!= IS_RESOURCE
) {
127 if (resource_type_name
) {
128 class_name
= get_active_class_name(&space TSRMLS_CC
);
129 zend_error(E_WARNING
, "%s%s%s(): supplied argument is not a valid %s resource", class_name
, space
, get_active_function_name(TSRMLS_C
), resource_type_name
);
133 id
= (*passed_id
)->value
.lval
;
138 resource
= zend_list_find(id
, &actual_resource_type
);
140 if (resource_type_name
) {
141 class_name
= get_active_class_name(&space TSRMLS_CC
);
142 zend_error(E_WARNING
, "%s%s%s(): %d is not a valid %s resource", class_name
, space
, get_active_function_name(TSRMLS_C
), id
, resource_type_name
);
147 va_start(resource_types
, num_resource_types
);
148 for (i
=0; i
<num_resource_types
; i
++) {
149 if (actual_resource_type
== va_arg(resource_types
, int)) {
150 va_end(resource_types
);
151 if (found_resource_type
) {
152 *found_resource_type
= actual_resource_type
;
157 va_end(resource_types
);
159 if (resource_type_name
) {
160 class_name
= get_active_class_name(&space TSRMLS_CC
);
161 zend_error(E_WARNING
, "%s%s%s(): supplied resource is not a valid %s resource", class_name
, space
, get_active_function_name(TSRMLS_C
), resource_type_name
);
168 void list_entry_destructor(void *ptr
)
170 zend_rsrc_list_entry
*le
= (zend_rsrc_list_entry
*) ptr
;
171 zend_rsrc_list_dtors_entry
*ld
;
174 if (zend_hash_index_find(&list_destructors
, le
->type
, (void **) &ld
)==SUCCESS
) {
176 case ZEND_RESOURCE_LIST_TYPE_STD
:
178 (ld
->list_dtor
)(le
->ptr
);
181 case ZEND_RESOURCE_LIST_TYPE_EX
:
182 if (ld
->list_dtor_ex
) {
183 ld
->list_dtor_ex(le TSRMLS_CC
);
186 EMPTY_SWITCH_DEFAULT_CASE()
189 zend_error(E_WARNING
,"Unknown list entry type in request shutdown (%d)", le
->type
);
194 void plist_entry_destructor(void *ptr
)
196 zend_rsrc_list_entry
*le
= (zend_rsrc_list_entry
*) ptr
;
197 zend_rsrc_list_dtors_entry
*ld
;
200 if (zend_hash_index_find(&list_destructors
, le
->type
, (void **) &ld
)==SUCCESS
) {
202 case ZEND_RESOURCE_LIST_TYPE_STD
:
203 if (ld
->plist_dtor
) {
204 (ld
->plist_dtor
)(le
->ptr
);
207 case ZEND_RESOURCE_LIST_TYPE_EX
:
208 if (ld
->plist_dtor_ex
) {
209 ld
->plist_dtor_ex(le TSRMLS_CC
);
212 EMPTY_SWITCH_DEFAULT_CASE()
215 zend_error(E_WARNING
,"Unknown persistent list entry type in module shutdown (%d)", le
->type
);
220 int zend_init_rsrc_list(TSRMLS_D
)
222 if (zend_hash_init(&EG(regular_list
), 0, NULL
, list_entry_destructor
, 0)==SUCCESS
) {
223 EG(regular_list
).nNextFreeElement
=1; /* we don't want resource id 0 */
231 int zend_init_rsrc_plist(TSRMLS_D
)
233 return zend_hash_init_ex(&EG(persistent_list
), 0, NULL
, plist_entry_destructor
, 1, 0);
237 void zend_destroy_rsrc_list(HashTable
*ht TSRMLS_DC
)
239 zend_hash_graceful_reverse_destroy(ht
);
242 static int clean_module_resource(zend_rsrc_list_entry
*le
, int *resource_id TSRMLS_DC
)
244 if (le
->type
== *resource_id
) {
252 static int zend_clean_module_rsrc_dtors_cb(zend_rsrc_list_dtors_entry
*ld
, int *module_number TSRMLS_DC
)
254 if (ld
->module_number
== *module_number
) {
255 zend_hash_apply_with_argument(&EG(persistent_list
), (apply_func_arg_t
) clean_module_resource
, (void *) &(ld
->resource_id
) TSRMLS_CC
);
263 void zend_clean_module_rsrc_dtors(int module_number TSRMLS_DC
)
265 zend_hash_apply_with_argument(&list_destructors
, (apply_func_arg_t
) zend_clean_module_rsrc_dtors_cb
, (void *) &module_number TSRMLS_CC
);
269 ZEND_API
int zend_register_list_destructors(void (*ld
)(void *), void (*pld
)(void *), int module_number
)
271 zend_rsrc_list_dtors_entry lde
;
274 printf("Registering destructors %d for module %d\n", list_destructors
.nNextFreeElement
, module_number
);
277 lde
.list_dtor
=(void (*)(void *)) ld
;
278 lde
.plist_dtor
=(void (*)(void *)) pld
;
279 lde
.list_dtor_ex
= lde
.plist_dtor_ex
= NULL
;
280 lde
.module_number
= module_number
;
281 lde
.resource_id
= list_destructors
.nNextFreeElement
;
282 lde
.type
= ZEND_RESOURCE_LIST_TYPE_STD
;
283 lde
.type_name
= NULL
;
285 if (zend_hash_next_index_insert(&list_destructors
, (void *) &lde
, sizeof(zend_rsrc_list_dtors_entry
), NULL
)==FAILURE
) {
288 return list_destructors
.nNextFreeElement
-1;
292 ZEND_API
int zend_register_list_destructors_ex(rsrc_dtor_func_t ld
, rsrc_dtor_func_t pld
, const char *type_name
, int module_number
)
294 zend_rsrc_list_dtors_entry lde
;
297 printf("Registering destructors %d for module %d\n", list_destructors
.nNextFreeElement
, module_number
);
300 lde
.list_dtor
= NULL
;
301 lde
.plist_dtor
= NULL
;
302 lde
.list_dtor_ex
= ld
;
303 lde
.plist_dtor_ex
= pld
;
304 lde
.module_number
= module_number
;
305 lde
.resource_id
= list_destructors
.nNextFreeElement
;
306 lde
.type
= ZEND_RESOURCE_LIST_TYPE_EX
;
307 lde
.type_name
= type_name
;
309 if (zend_hash_next_index_insert(&list_destructors
, (void *) &lde
, sizeof(zend_rsrc_list_dtors_entry
), NULL
)==FAILURE
) {
312 return list_destructors
.nNextFreeElement
-1;
315 ZEND_API
int zend_fetch_list_dtor_id(char *type_name
)
317 zend_rsrc_list_dtors_entry
*lde
;
320 zend_hash_internal_pointer_reset_ex(&list_destructors
, &pos
);
321 while (zend_hash_get_current_data_ex(&list_destructors
, (void **)&lde
, &pos
) == SUCCESS
) {
322 if (lde
->type_name
&& (strcmp(type_name
, lde
->type_name
) == 0)) {
324 printf("Found resource id %d for resource type %s\n", (*lde
).resource_id
, type_name
);
326 return lde
->resource_id
;
328 zend_hash_move_forward_ex(&list_destructors
, &pos
);
334 int zend_init_rsrc_list_dtors(void)
338 retval
= zend_hash_init(&list_destructors
, 50, NULL
, NULL
, 1);
339 list_destructors
.nNextFreeElement
=1; /* we don't want resource type 0 */
345 void zend_destroy_rsrc_list_dtors(void)
347 zend_hash_destroy(&list_destructors
);
351 const char *zend_rsrc_list_get_rsrc_type(int resource TSRMLS_DC
)
353 zend_rsrc_list_dtors_entry
*lde
;
356 if (!zend_list_find(resource
, &rsrc_type
))
359 if (zend_hash_index_find(&list_destructors
, rsrc_type
, (void **) &lde
)==SUCCESS
) {
360 return lde
->type_name
;
370 * indent-tabs-mode: t