zend_interfaces.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574
  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: Marcus Boerger <helly@php.net> |
  16. +----------------------------------------------------------------------+
  17. */
  18. /* $Id$ */
  19. #include "zend.h"
  20. #include "zend_API.h"
  21. #include "zend_interfaces.h"
  22. #include "zend_exceptions.h"
  23. ZEND_API zend_class_entry *zend_ce_traversable;
  24. ZEND_API zend_class_entry *zend_ce_aggregate;
  25. ZEND_API zend_class_entry *zend_ce_iterator;
  26. ZEND_API zend_class_entry *zend_ce_arrayaccess;
  27. ZEND_API zend_class_entry *zend_ce_serializable;
  28. /* {{{ zend_call_method
  29. Only returns the returned zval if retval_ptr != NULL */
  30. ZEND_API zval* zend_call_method(zval **object_pp, zend_class_entry *obj_ce, zend_function **fn_proxy, const char *function_name, int function_name_len, zval **retval_ptr_ptr, int param_count, zval* arg1, zval* arg2 TSRMLS_DC)
  31. {
  32. int result;
  33. zend_fcall_info fci;
  34. zval z_fname;
  35. zval *retval;
  36. HashTable *function_table;
  37. zval **params[2];
  38. params[0] = &arg1;
  39. params[1] = &arg2;
  40. fci.size = sizeof(fci);
  41. /*fci.function_table = NULL; will be read form zend_class_entry of object if needed */
  42. fci.object_ptr = object_pp ? *object_pp : NULL;
  43. fci.function_name = &z_fname;
  44. fci.retval_ptr_ptr = retval_ptr_ptr ? retval_ptr_ptr : &retval;
  45. fci.param_count = param_count;
  46. fci.params = params;
  47. fci.no_separation = 1;
  48. fci.symbol_table = NULL;
  49. if (!fn_proxy && !obj_ce) {
  50. /* no interest in caching and no information already present that is
  51. * needed later inside zend_call_function. */
  52. ZVAL_STRINGL(&z_fname, function_name, function_name_len, 0);
  53. fci.function_table = !object_pp ? EG(function_table) : NULL;
  54. result = zend_call_function(&fci, NULL TSRMLS_CC);
  55. } else {
  56. zend_fcall_info_cache fcic;
  57. fcic.initialized = 1;
  58. if (!obj_ce) {
  59. obj_ce = object_pp ? Z_OBJCE_PP(object_pp) : NULL;
  60. }
  61. if (obj_ce) {
  62. function_table = &obj_ce->function_table;
  63. } else {
  64. function_table = EG(function_table);
  65. }
  66. if (!fn_proxy || !*fn_proxy) {
  67. if (zend_hash_find(function_table, function_name, function_name_len+1, (void **) &fcic.function_handler) == FAILURE) {
  68. /* error at c-level */
  69. zend_error(E_CORE_ERROR, "Couldn't find implementation for method %s%s%s", obj_ce ? obj_ce->name : "", obj_ce ? "::" : "", function_name);
  70. }
  71. if (fn_proxy) {
  72. *fn_proxy = fcic.function_handler;
  73. }
  74. } else {
  75. fcic.function_handler = *fn_proxy;
  76. }
  77. fcic.calling_scope = obj_ce;
  78. if (object_pp) {
  79. fcic.called_scope = Z_OBJCE_PP(object_pp);
  80. } else if (obj_ce &&
  81. !(EG(called_scope) &&
  82. instanceof_function(EG(called_scope), obj_ce TSRMLS_CC))) {
  83. fcic.called_scope = obj_ce;
  84. } else {
  85. fcic.called_scope = EG(called_scope);
  86. }
  87. fcic.object_ptr = object_pp ? *object_pp : NULL;
  88. result = zend_call_function(&fci, &fcic TSRMLS_CC);
  89. }
  90. if (result == FAILURE) {
  91. /* error at c-level */
  92. if (!obj_ce) {
  93. obj_ce = object_pp ? Z_OBJCE_PP(object_pp) : NULL;
  94. }
  95. if (!EG(exception)) {
  96. zend_error(E_CORE_ERROR, "Couldn't execute method %s%s%s", obj_ce ? obj_ce->name : "", obj_ce ? "::" : "", function_name);
  97. }
  98. }
  99. if (!retval_ptr_ptr) {
  100. if (retval) {
  101. zval_ptr_dtor(&retval);
  102. }
  103. return NULL;
  104. }
  105. return *retval_ptr_ptr;
  106. }
  107. /* }}} */
  108. /* iterator interface, c-level functions used by engine */
  109. /* {{{ zend_user_it_new_iterator */
  110. ZEND_API zval *zend_user_it_new_iterator(zend_class_entry *ce, zval *object TSRMLS_DC)
  111. {
  112. zval *retval;
  113. return zend_call_method_with_0_params(&object, ce, &ce->iterator_funcs.zf_new_iterator, "getiterator", &retval);
  114. }
  115. /* }}} */
  116. /* {{{ zend_user_it_invalidate_current */
  117. ZEND_API void zend_user_it_invalidate_current(zend_object_iterator *_iter TSRMLS_DC)
  118. {
  119. zend_user_iterator *iter = (zend_user_iterator*)_iter;
  120. if (iter->value) {
  121. zval_ptr_dtor(&iter->value);
  122. iter->value = NULL;
  123. }
  124. }
  125. /* }}} */
  126. /* {{{ zend_user_it_dtor */
  127. static void zend_user_it_dtor(zend_object_iterator *_iter TSRMLS_DC)
  128. {
  129. zend_user_iterator *iter = (zend_user_iterator*)_iter;
  130. zval *object = (zval*)iter->it.data;
  131. zend_user_it_invalidate_current(_iter TSRMLS_CC);
  132. zval_ptr_dtor(&object);
  133. efree(iter);
  134. }
  135. /* }}} */
  136. /* {{{ zend_user_it_valid */
  137. ZEND_API int zend_user_it_valid(zend_object_iterator *_iter TSRMLS_DC)
  138. {
  139. if (_iter) {
  140. zend_user_iterator *iter = (zend_user_iterator*)_iter;
  141. zval *object = (zval*)iter->it.data;
  142. zval *more;
  143. int result;
  144. zend_call_method_with_0_params(&object, iter->ce, &iter->ce->iterator_funcs.zf_valid, "valid", &more);
  145. if (more) {
  146. result = i_zend_is_true(more);
  147. zval_ptr_dtor(&more);
  148. return result ? SUCCESS : FAILURE;
  149. }
  150. }
  151. return FAILURE;
  152. }
  153. /* }}} */
  154. /* {{{ zend_user_it_get_current_data */
  155. ZEND_API void zend_user_it_get_current_data(zend_object_iterator *_iter, zval ***data TSRMLS_DC)
  156. {
  157. zend_user_iterator *iter = (zend_user_iterator*)_iter;
  158. zval *object = (zval*)iter->it.data;
  159. if (!iter->value) {
  160. zend_call_method_with_0_params(&object, iter->ce, &iter->ce->iterator_funcs.zf_current, "current", &iter->value);
  161. }
  162. *data = &iter->value;
  163. }
  164. /* }}} */
  165. /* {{{ zend_user_it_get_current_key_default */
  166. #if 0
  167. static int zend_user_it_get_current_key_default(zend_object_iterator *_iter, char **str_key, uint *str_key_len, ulong *int_key TSRMLS_DC)
  168. {
  169. *int_key = _iter->index;
  170. return HASH_KEY_IS_LONG;
  171. }
  172. #endif
  173. /* }}} */
  174. /* {{{ zend_user_it_get_current_key */
  175. ZEND_API void zend_user_it_get_current_key(zend_object_iterator *_iter, zval *key TSRMLS_DC)
  176. {
  177. zend_user_iterator *iter = (zend_user_iterator*)_iter;
  178. zval *object = (zval*)iter->it.data;
  179. zval *retval;
  180. zend_call_method_with_0_params(&object, iter->ce, &iter->ce->iterator_funcs.zf_key, "key", &retval);
  181. if (retval) {
  182. ZVAL_ZVAL(key, retval, 1, 1);
  183. } else {
  184. if (!EG(exception)) {
  185. zend_error(E_WARNING, "Nothing returned from %s::key()", iter->ce->name);
  186. }
  187. ZVAL_LONG(key, 0);
  188. }
  189. }
  190. /* {{{ zend_user_it_move_forward */
  191. ZEND_API void zend_user_it_move_forward(zend_object_iterator *_iter TSRMLS_DC)
  192. {
  193. zend_user_iterator *iter = (zend_user_iterator*)_iter;
  194. zval *object = (zval*)iter->it.data;
  195. zend_user_it_invalidate_current(_iter TSRMLS_CC);
  196. zend_call_method_with_0_params(&object, iter->ce, &iter->ce->iterator_funcs.zf_next, "next", NULL);
  197. }
  198. /* }}} */
  199. /* {{{ zend_user_it_rewind */
  200. ZEND_API void zend_user_it_rewind(zend_object_iterator *_iter TSRMLS_DC)
  201. {
  202. zend_user_iterator *iter = (zend_user_iterator*)_iter;
  203. zval *object = (zval*)iter->it.data;
  204. zend_user_it_invalidate_current(_iter TSRMLS_CC);
  205. zend_call_method_with_0_params(&object, iter->ce, &iter->ce->iterator_funcs.zf_rewind, "rewind", NULL);
  206. }
  207. /* }}} */
  208. zend_object_iterator_funcs zend_interface_iterator_funcs_iterator = {
  209. zend_user_it_dtor,
  210. zend_user_it_valid,
  211. zend_user_it_get_current_data,
  212. zend_user_it_get_current_key,
  213. zend_user_it_move_forward,
  214. zend_user_it_rewind,
  215. zend_user_it_invalidate_current
  216. };
  217. /* {{{ zend_user_it_get_iterator */
  218. static zend_object_iterator *zend_user_it_get_iterator(zend_class_entry *ce, zval *object, int by_ref TSRMLS_DC)
  219. {
  220. zend_user_iterator *iterator;
  221. if (by_ref) {
  222. zend_error(E_ERROR, "An iterator cannot be used with foreach by reference");
  223. }
  224. iterator = emalloc(sizeof(zend_user_iterator));
  225. Z_ADDREF_P(object);
  226. iterator->it.data = (void*)object;
  227. iterator->it.funcs = ce->iterator_funcs.funcs;
  228. iterator->ce = Z_OBJCE_P(object);
  229. iterator->value = NULL;
  230. return (zend_object_iterator*)iterator;
  231. }
  232. /* }}} */
  233. /* {{{ zend_user_it_get_new_iterator */
  234. ZEND_API zend_object_iterator *zend_user_it_get_new_iterator(zend_class_entry *ce, zval *object, int by_ref TSRMLS_DC)
  235. {
  236. zval *iterator = zend_user_it_new_iterator(ce, object TSRMLS_CC);
  237. zend_object_iterator *new_iterator;
  238. zend_class_entry *ce_it = iterator && Z_TYPE_P(iterator) == IS_OBJECT ? Z_OBJCE_P(iterator) : NULL;
  239. if (!ce_it || !ce_it->get_iterator || (ce_it->get_iterator == zend_user_it_get_new_iterator && iterator == object)) {
  240. if (!EG(exception)) {
  241. zend_throw_exception_ex(NULL, 0 TSRMLS_CC, "Objects returned by %s::getIterator() must be traversable or implement interface Iterator", ce ? ce->name : Z_OBJCE_P(object)->name);
  242. }
  243. if (iterator) {
  244. zval_ptr_dtor(&iterator);
  245. }
  246. return NULL;
  247. }
  248. new_iterator = ce_it->get_iterator(ce_it, iterator, by_ref TSRMLS_CC);
  249. zval_ptr_dtor(&iterator);
  250. return new_iterator;
  251. }
  252. /* }}} */
  253. /* {{{ zend_implement_traversable */
  254. static int zend_implement_traversable(zend_class_entry *interface, zend_class_entry *class_type TSRMLS_DC)
  255. {
  256. /* check that class_type is traversable at c-level or implements at least one of 'aggregate' and 'Iterator' */
  257. zend_uint i;
  258. if (class_type->get_iterator || (class_type->parent && class_type->parent->get_iterator)) {
  259. return SUCCESS;
  260. }
  261. for (i = 0; i < class_type->num_interfaces; i++) {
  262. if (class_type->interfaces[i] == zend_ce_aggregate || class_type->interfaces[i] == zend_ce_iterator) {
  263. return SUCCESS;
  264. }
  265. }
  266. zend_error(E_CORE_ERROR, "Class %s must implement interface %s as part of either %s or %s",
  267. class_type->name,
  268. zend_ce_traversable->name,
  269. zend_ce_iterator->name,
  270. zend_ce_aggregate->name);
  271. return FAILURE;
  272. }
  273. /* }}} */
  274. /* {{{ zend_implement_aggregate */
  275. static int zend_implement_aggregate(zend_class_entry *interface, zend_class_entry *class_type TSRMLS_DC)
  276. {
  277. int i, t = -1;
  278. if (class_type->get_iterator) {
  279. if (class_type->type == ZEND_INTERNAL_CLASS) {
  280. /* inheritance ensures the class has necessary userland methods */
  281. return SUCCESS;
  282. } else if (class_type->get_iterator != zend_user_it_get_new_iterator) {
  283. /* c-level get_iterator cannot be changed (exception being only Traversable is implmented) */
  284. if (class_type->num_interfaces) {
  285. for (i = 0; i < class_type->num_interfaces; i++) {
  286. if (class_type->interfaces[i] == zend_ce_iterator) {
  287. zend_error(E_ERROR, "Class %s cannot implement both %s and %s at the same time",
  288. class_type->name,
  289. interface->name,
  290. zend_ce_iterator->name);
  291. return FAILURE;
  292. }
  293. if (class_type->interfaces[i] == zend_ce_traversable) {
  294. t = i;
  295. }
  296. }
  297. }
  298. if (t == -1) {
  299. return FAILURE;
  300. }
  301. }
  302. }
  303. class_type->iterator_funcs.zf_new_iterator = NULL;
  304. class_type->get_iterator = zend_user_it_get_new_iterator;
  305. return SUCCESS;
  306. }
  307. /* }}} */
  308. /* {{{ zend_implement_iterator */
  309. static int zend_implement_iterator(zend_class_entry *interface, zend_class_entry *class_type TSRMLS_DC)
  310. {
  311. if (class_type->get_iterator && class_type->get_iterator != zend_user_it_get_iterator) {
  312. if (class_type->type == ZEND_INTERNAL_CLASS) {
  313. /* inheritance ensures the class has the necessary userland methods */
  314. return SUCCESS;
  315. } else {
  316. /* c-level get_iterator cannot be changed */
  317. if (class_type->get_iterator == zend_user_it_get_new_iterator) {
  318. zend_error(E_ERROR, "Class %s cannot implement both %s and %s at the same time",
  319. class_type->name,
  320. interface->name,
  321. zend_ce_aggregate->name);
  322. }
  323. return FAILURE;
  324. }
  325. }
  326. class_type->get_iterator = zend_user_it_get_iterator;
  327. class_type->iterator_funcs.zf_valid = NULL;
  328. class_type->iterator_funcs.zf_current = NULL;
  329. class_type->iterator_funcs.zf_key = NULL;
  330. class_type->iterator_funcs.zf_next = NULL;
  331. class_type->iterator_funcs.zf_rewind = NULL;
  332. if (!class_type->iterator_funcs.funcs) {
  333. class_type->iterator_funcs.funcs = &zend_interface_iterator_funcs_iterator;
  334. }
  335. return SUCCESS;
  336. }
  337. /* }}} */
  338. /* {{{ zend_implement_arrayaccess */
  339. static int zend_implement_arrayaccess(zend_class_entry *interface, zend_class_entry *class_type TSRMLS_DC)
  340. {
  341. #if 0
  342. /* get ht from ce */
  343. if (ht->read_dimension != zend_std_read_dimension
  344. || ht->write_dimension != zend_std_write_dimension
  345. || ht->has_dimension != zend_std_has_dimension
  346. || ht->unset_dimension != zend_std_unset_dimension) {
  347. return FAILURE;
  348. }
  349. #endif
  350. return SUCCESS;
  351. }
  352. /* }}}*/
  353. /* {{{ zend_user_serialize */
  354. ZEND_API int zend_user_serialize(zval *object, unsigned char **buffer, zend_uint *buf_len, zend_serialize_data *data TSRMLS_DC)
  355. {
  356. zend_class_entry * ce = Z_OBJCE_P(object);
  357. zval *retval;
  358. int result;
  359. zend_call_method_with_0_params(&object, ce, &ce->serialize_func, "serialize", &retval);
  360. if (!retval || EG(exception)) {
  361. result = FAILURE;
  362. } else {
  363. switch(Z_TYPE_P(retval)) {
  364. case IS_NULL:
  365. /* we could also make this '*buf_len = 0' but this allows to skip variables */
  366. zval_ptr_dtor(&retval);
  367. return FAILURE;
  368. case IS_STRING:
  369. *buffer = (unsigned char*)estrndup(Z_STRVAL_P(retval), Z_STRLEN_P(retval));
  370. *buf_len = Z_STRLEN_P(retval);
  371. result = SUCCESS;
  372. break;
  373. default: /* failure */
  374. result = FAILURE;
  375. break;
  376. }
  377. zval_ptr_dtor(&retval);
  378. }
  379. if (result == FAILURE && !EG(exception)) {
  380. zend_throw_exception_ex(NULL, 0 TSRMLS_CC, "%s::serialize() must return a string or NULL", ce->name);
  381. }
  382. return result;
  383. }
  384. /* }}} */
  385. /* {{{ zend_user_unserialize */
  386. ZEND_API int zend_user_unserialize(zval **object, zend_class_entry *ce, const unsigned char *buf, zend_uint buf_len, zend_unserialize_data *data TSRMLS_DC)
  387. {
  388. zval * zdata;
  389. object_init_ex(*object, ce);
  390. MAKE_STD_ZVAL(zdata);
  391. ZVAL_STRINGL(zdata, (char*)buf, buf_len, 1);
  392. zend_call_method_with_1_params(object, ce, &ce->unserialize_func, "unserialize", NULL, zdata);
  393. zval_ptr_dtor(&zdata);
  394. if (EG(exception)) {
  395. return FAILURE;
  396. } else {
  397. return SUCCESS;
  398. }
  399. }
  400. /* }}} */
  401. ZEND_API int zend_class_serialize_deny(zval *object, unsigned char **buffer, zend_uint *buf_len, zend_serialize_data *data TSRMLS_DC) /* {{{ */
  402. {
  403. zend_class_entry *ce = Z_OBJCE_P(object);
  404. zend_throw_exception_ex(NULL, 0 TSRMLS_CC, "Serialization of '%s' is not allowed", ce->name);
  405. return FAILURE;
  406. }
  407. /* }}} */
  408. ZEND_API int zend_class_unserialize_deny(zval **object, zend_class_entry *ce, const unsigned char *buf, zend_uint buf_len, zend_unserialize_data *data TSRMLS_DC) /* {{{ */
  409. {
  410. zend_throw_exception_ex(NULL, 0 TSRMLS_CC, "Unserialization of '%s' is not allowed", ce->name);
  411. return FAILURE;
  412. }
  413. /* }}} */
  414. /* {{{ zend_implement_serializable */
  415. static int zend_implement_serializable(zend_class_entry *interface, zend_class_entry *class_type TSRMLS_DC)
  416. {
  417. if (class_type->parent
  418. && (class_type->parent->serialize || class_type->parent->unserialize)
  419. && !instanceof_function_ex(class_type->parent, zend_ce_serializable, 1 TSRMLS_CC)) {
  420. return FAILURE;
  421. }
  422. if (!class_type->serialize) {
  423. class_type->serialize = zend_user_serialize;
  424. }
  425. if (!class_type->unserialize) {
  426. class_type->unserialize = zend_user_unserialize;
  427. }
  428. return SUCCESS;
  429. }
  430. /* }}}*/
  431. /* {{{ function tables */
  432. const zend_function_entry zend_funcs_aggregate[] = {
  433. ZEND_ABSTRACT_ME(iterator, getIterator, NULL)
  434. {NULL, NULL, NULL}
  435. };
  436. const zend_function_entry zend_funcs_iterator[] = {
  437. ZEND_ABSTRACT_ME(iterator, current, NULL)
  438. ZEND_ABSTRACT_ME(iterator, next, NULL)
  439. ZEND_ABSTRACT_ME(iterator, key, NULL)
  440. ZEND_ABSTRACT_ME(iterator, valid, NULL)
  441. ZEND_ABSTRACT_ME(iterator, rewind, NULL)
  442. {NULL, NULL, NULL}
  443. };
  444. const zend_function_entry *zend_funcs_traversable = NULL;
  445. ZEND_BEGIN_ARG_INFO_EX(arginfo_arrayaccess_offset, 0, 0, 1)
  446. ZEND_ARG_INFO(0, offset)
  447. ZEND_END_ARG_INFO()
  448. ZEND_BEGIN_ARG_INFO_EX(arginfo_arrayaccess_offset_get, 0, 0, 1) /* actually this should be return by ref but atm cannot be */
  449. ZEND_ARG_INFO(0, offset)
  450. ZEND_END_ARG_INFO()
  451. ZEND_BEGIN_ARG_INFO_EX(arginfo_arrayaccess_offset_value, 0, 0, 2)
  452. ZEND_ARG_INFO(0, offset)
  453. ZEND_ARG_INFO(0, value)
  454. ZEND_END_ARG_INFO()
  455. const zend_function_entry zend_funcs_arrayaccess[] = {
  456. ZEND_ABSTRACT_ME(arrayaccess, offsetExists, arginfo_arrayaccess_offset)
  457. ZEND_ABSTRACT_ME(arrayaccess, offsetGet, arginfo_arrayaccess_offset_get)
  458. ZEND_ABSTRACT_ME(arrayaccess, offsetSet, arginfo_arrayaccess_offset_value)
  459. ZEND_ABSTRACT_ME(arrayaccess, offsetUnset, arginfo_arrayaccess_offset)
  460. {NULL, NULL, NULL}
  461. };
  462. ZEND_BEGIN_ARG_INFO(arginfo_serializable_serialize, 0)
  463. ZEND_ARG_INFO(0, serialized)
  464. ZEND_END_ARG_INFO()
  465. const zend_function_entry zend_funcs_serializable[] = {
  466. ZEND_ABSTRACT_ME(serializable, serialize, NULL)
  467. ZEND_FENTRY(unserialize, NULL, arginfo_serializable_serialize, ZEND_ACC_PUBLIC|ZEND_ACC_ABSTRACT|ZEND_ACC_CTOR)
  468. {NULL, NULL, NULL}
  469. };
  470. /* }}} */
  471. #define REGISTER_ITERATOR_INTERFACE(class_name, class_name_str) \
  472. {\
  473. zend_class_entry ce;\
  474. INIT_CLASS_ENTRY(ce, # class_name_str, zend_funcs_ ## class_name) \
  475. zend_ce_ ## class_name = zend_register_internal_interface(&ce TSRMLS_CC);\
  476. zend_ce_ ## class_name->interface_gets_implemented = zend_implement_ ## class_name;\
  477. }
  478. #define REGISTER_ITERATOR_IMPLEMENT(class_name, interface_name) \
  479. zend_class_implements(zend_ce_ ## class_name TSRMLS_CC, 1, zend_ce_ ## interface_name)
  480. /* {{{ zend_register_interfaces */
  481. ZEND_API void zend_register_interfaces(TSRMLS_D)
  482. {
  483. REGISTER_ITERATOR_INTERFACE(traversable, Traversable);
  484. REGISTER_ITERATOR_INTERFACE(aggregate, IteratorAggregate);
  485. REGISTER_ITERATOR_IMPLEMENT(aggregate, traversable);
  486. REGISTER_ITERATOR_INTERFACE(iterator, Iterator);
  487. REGISTER_ITERATOR_IMPLEMENT(iterator, traversable);
  488. REGISTER_ITERATOR_INTERFACE(arrayaccess, ArrayAccess);
  489. REGISTER_ITERATOR_INTERFACE(serializable, Serializable)
  490. }
  491. /* }}} */
  492. /*
  493. * Local variables:
  494. * tab-width: 4
  495. * c-basic-offset: 4
  496. * indent-tabs-mode: t
  497. * End:
  498. */