zend_interfaces.c 19 KB

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