root/Zend/zend_list.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. zend_list_insert
  2. _zend_list_delete
  3. _zend_list_find
  4. _zend_list_addref
  5. zend_register_resource
  6. zend_fetch_resource
  7. list_entry_destructor
  8. plist_entry_destructor
  9. zend_init_rsrc_list
  10. zend_init_rsrc_plist
  11. zend_destroy_rsrc_list
  12. clean_module_resource
  13. zend_clean_module_rsrc_dtors_cb
  14. zend_clean_module_rsrc_dtors
  15. zend_register_list_destructors
  16. zend_register_list_destructors_ex
  17. zend_fetch_list_dtor_id
  18. zend_init_rsrc_list_dtors
  19. zend_destroy_rsrc_list_dtors
  20. zend_rsrc_list_get_rsrc_type

   1 /*
   2    +----------------------------------------------------------------------+
   3    | Zend Engine                                                          |
   4    +----------------------------------------------------------------------+
   5    | Copyright (c) 1998-2016 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    +----------------------------------------------------------------------+
  18 */
  19 
  20 /* $Id$ */
  21 
  22 /* resource lists */
  23 
  24 #include "zend.h"
  25 #include "zend_list.h"
  26 #include "zend_API.h"
  27 #include "zend_globals.h"
  28 
  29 ZEND_API int le_index_ptr;
  30 
  31 /* true global */
  32 static HashTable list_destructors;
  33 
  34 
  35 ZEND_API int zend_list_insert(void *ptr, int type TSRMLS_DC)
  36 {
  37         int index;
  38         zend_rsrc_list_entry le;
  39 
  40         le.ptr=ptr;
  41         le.type=type;
  42         le.refcount=1;
  43 
  44         index = zend_hash_next_free_element(&EG(regular_list));
  45 
  46         zend_hash_index_update(&EG(regular_list), index, (void *) &le, sizeof(zend_rsrc_list_entry), NULL);
  47         return index;
  48 }
  49 
  50 ZEND_API int _zend_list_delete(int id TSRMLS_DC)
  51 {
  52         zend_rsrc_list_entry *le;
  53         
  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);
  58                 } else {
  59                         return SUCCESS;
  60                 }
  61         } else {
  62                 return FAILURE;
  63         }
  64 }
  65 
  66 
  67 ZEND_API void *_zend_list_find(int id, int *type TSRMLS_DC)
  68 {
  69         zend_rsrc_list_entry *le;
  70 
  71         if (zend_hash_index_find(&EG(regular_list), id, (void **) &le)==SUCCESS) {
  72                 *type = le->type;
  73                 return le->ptr;
  74         } else {
  75                 *type = -1;
  76                 return NULL;
  77         }
  78 }
  79 
  80 ZEND_API int _zend_list_addref(int id TSRMLS_DC)
  81 {
  82         zend_rsrc_list_entry *le;
  83         
  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); */
  86                 le->refcount++;
  87                 return SUCCESS;
  88         } else {
  89                 return FAILURE;
  90         }
  91 }
  92 
  93 
  94 ZEND_API int zend_register_resource(zval *rsrc_result, void *rsrc_pointer, int rsrc_type TSRMLS_DC)
  95 {
  96         int rsrc_id;
  97 
  98         rsrc_id = zend_list_insert(rsrc_pointer, rsrc_type TSRMLS_CC);
  99         
 100         if (rsrc_result) {
 101                 rsrc_result->value.lval = rsrc_id;
 102                 rsrc_result->type = IS_RESOURCE;
 103         }
 104 
 105         return rsrc_id;
 106 }
 107 
 108 
 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, ...)
 110 {
 111         int id;
 112         int actual_resource_type;
 113         void *resource;
 114         va_list resource_types;
 115         int i;
 116         const char *space;
 117         const char *class_name;
 118 
 119         if (default_id==-1) { /* use id */
 120                 if (!passed_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);
 124                         }
 125                         return NULL;
 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);
 130                         }
 131                         return NULL;
 132                 }
 133                 id = (*passed_id)->value.lval;
 134         } else {
 135                 id = default_id;
 136         }
 137 
 138         resource = zend_list_find(id, &actual_resource_type);
 139         if (!resource) {
 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);
 143                 }
 144                 return NULL;
 145         }
 146 
 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;
 153                         }
 154                         return resource;
 155                 }
 156         }
 157         va_end(resource_types);
 158 
 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);
 162         }
 163 
 164         return NULL;
 165 }
 166 
 167 
 168 void list_entry_destructor(void *ptr)
 169 {
 170         zend_rsrc_list_entry *le = (zend_rsrc_list_entry *) ptr;
 171         zend_rsrc_list_dtors_entry *ld;
 172         TSRMLS_FETCH();
 173         
 174         if (zend_hash_index_find(&list_destructors, le->type, (void **) &ld)==SUCCESS) {
 175                 switch (ld->type) {
 176                         case ZEND_RESOURCE_LIST_TYPE_STD:
 177                                 if (ld->list_dtor) {
 178                                         (ld->list_dtor)(le->ptr);
 179                                 }
 180                                 break;
 181                         case ZEND_RESOURCE_LIST_TYPE_EX:
 182                                 if (ld->list_dtor_ex) {
 183                                         ld->list_dtor_ex(le TSRMLS_CC);
 184                                 }
 185                                 break;
 186                         EMPTY_SWITCH_DEFAULT_CASE()
 187                 }
 188         } else {
 189                 zend_error(E_WARNING,"Unknown list entry type in request shutdown (%d)", le->type);
 190         }
 191 }
 192 
 193 
 194 void plist_entry_destructor(void *ptr)
 195 {
 196         zend_rsrc_list_entry *le = (zend_rsrc_list_entry *) ptr;
 197         zend_rsrc_list_dtors_entry *ld;
 198         TSRMLS_FETCH();
 199 
 200         if (zend_hash_index_find(&list_destructors, le->type, (void **) &ld)==SUCCESS) {
 201                 switch (ld->type) {
 202                         case ZEND_RESOURCE_LIST_TYPE_STD:
 203                                 if (ld->plist_dtor) {
 204                                         (ld->plist_dtor)(le->ptr);
 205                                 }
 206                                 break;
 207                         case ZEND_RESOURCE_LIST_TYPE_EX:
 208                                 if (ld->plist_dtor_ex) {
 209                                         ld->plist_dtor_ex(le TSRMLS_CC);
 210                                 }
 211                                 break;
 212                                 EMPTY_SWITCH_DEFAULT_CASE()
 213                 }
 214         } else {
 215                 zend_error(E_WARNING,"Unknown persistent list entry type in module shutdown (%d)", le->type);
 216         }
 217 }
 218 
 219 
 220 int zend_init_rsrc_list(TSRMLS_D)
 221 {
 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 */
 224                 return SUCCESS;
 225         } else {
 226                 return FAILURE;
 227         }
 228 }
 229 
 230 
 231 int zend_init_rsrc_plist(TSRMLS_D)
 232 {
 233         return zend_hash_init_ex(&EG(persistent_list), 0, NULL, plist_entry_destructor, 1, 0);
 234 }
 235 
 236 
 237 void zend_destroy_rsrc_list(HashTable *ht TSRMLS_DC)
 238 {
 239         zend_hash_graceful_reverse_destroy(ht);
 240 }
 241 
 242 static int clean_module_resource(zend_rsrc_list_entry *le, int *resource_id TSRMLS_DC)
 243 {
 244         if (le->type == *resource_id) {
 245                 return 1;
 246         } else {
 247                 return 0;
 248         }
 249 }
 250 
 251 
 252 static int zend_clean_module_rsrc_dtors_cb(zend_rsrc_list_dtors_entry *ld, int *module_number TSRMLS_DC)
 253 {
 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);
 256                 return 1;
 257         } else {
 258                 return 0;
 259         }
 260 }
 261 
 262 
 263 void zend_clean_module_rsrc_dtors(int module_number TSRMLS_DC)
 264 {
 265         zend_hash_apply_with_argument(&list_destructors, (apply_func_arg_t) zend_clean_module_rsrc_dtors_cb, (void *) &module_number TSRMLS_CC);
 266 }
 267 
 268 
 269 ZEND_API int zend_register_list_destructors(void (*ld)(void *), void (*pld)(void *), int module_number)
 270 {
 271         zend_rsrc_list_dtors_entry lde;
 272         
 273 #if 0
 274         printf("Registering destructors %d for module %d\n", list_destructors.nNextFreeElement, module_number);
 275 #endif
 276         
 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;
 284         
 285         if (zend_hash_next_index_insert(&list_destructors, (void *) &lde, sizeof(zend_rsrc_list_dtors_entry), NULL)==FAILURE) {
 286                 return FAILURE;
 287         }
 288         return list_destructors.nNextFreeElement-1;
 289 }
 290 
 291 
 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)
 293 {
 294         zend_rsrc_list_dtors_entry lde;
 295         
 296 #if 0
 297         printf("Registering destructors %d for module %d\n", list_destructors.nNextFreeElement, module_number);
 298 #endif
 299 
 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;
 308         
 309         if (zend_hash_next_index_insert(&list_destructors, (void *) &lde, sizeof(zend_rsrc_list_dtors_entry), NULL)==FAILURE) {
 310                 return FAILURE;
 311         }
 312         return list_destructors.nNextFreeElement-1;
 313 }
 314 
 315 ZEND_API int zend_fetch_list_dtor_id(char *type_name)
 316 {
 317         zend_rsrc_list_dtors_entry *lde;
 318         HashPosition pos;
 319 
 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)) {
 323 #if 0
 324                         printf("Found resource id %d for resource type %s\n", (*lde).resource_id, type_name);
 325 #endif
 326                         return lde->resource_id;
 327                 }
 328                 zend_hash_move_forward_ex(&list_destructors, &pos);
 329         }
 330 
 331         return 0;
 332 }
 333 
 334 int zend_init_rsrc_list_dtors(void)
 335 {
 336         int retval;
 337 
 338         retval = zend_hash_init(&list_destructors, 50, NULL, NULL, 1);
 339         list_destructors.nNextFreeElement=1;    /* we don't want resource type 0 */
 340 
 341         return retval;
 342 }
 343 
 344 
 345 void zend_destroy_rsrc_list_dtors(void)
 346 {
 347         zend_hash_destroy(&list_destructors);
 348 }
 349 
 350 
 351 const char *zend_rsrc_list_get_rsrc_type(int resource TSRMLS_DC)
 352 {
 353         zend_rsrc_list_dtors_entry *lde;
 354         int rsrc_type;
 355 
 356         if (!zend_list_find(resource, &rsrc_type))
 357                 return NULL;
 358 
 359         if (zend_hash_index_find(&list_destructors, rsrc_type, (void **) &lde)==SUCCESS) {
 360                 return lde->type_name;
 361         } else {
 362                 return NULL;
 363         }
 364 }
 365 
 366 /*
 367  * Local variables:
 368  * tab-width: 4
 369  * c-basic-offset: 4
 370  * indent-tabs-mode: t
 371  * End:
 372  */

/* [<][>][^][v][top][bottom][index][help] */