--- /dev/null
+--TEST--
+Test Z_PARAM_ITERABLE() and Z_PARAM_ITERABLE_OR_NULL
+--SKIPIF--
+<?php
+if (!extension_loaded('zend-test')) die('skip zend-test extension not loaded');
+?>
+--FILE--
+<?php
+
+try {
+ var_dump(zend_iterable("string"));
+} catch (TypeError $exception) {
+ echo $exception->getMessage() . "\n";
+}
+
+try {
+ var_dump(zend_iterable(1));
+} catch (TypeError $exception) {
+ echo $exception->getMessage() . "\n";
+}
+
+try {
+ var_dump(zend_iterable(null));
+} catch (TypeError $exception) {
+ echo $exception->getMessage() . "\n";
+}
+
+
+zend_iterable([]);
+zend_iterable([], []);
+
+$iterator = new ArrayIterator([]);
+zend_iterable($iterator);
+zend_iterable($iterator, $iterator);
+zend_iterable($iterator, null);
+
+try {
+ var_dump(zend_iterable([], "string"));
+} catch (TypeError $exception) {
+ echo $exception->getMessage() . "\n";
+}
+
+?>
+--EXPECT--
+zend_iterable(): Argument #1 ($arg1) must be of type iterable, string given
+zend_iterable(): Argument #1 ($arg1) must be of type iterable, int given
+zend_iterable(): Argument #1 ($arg1) must be of type iterable, null given
+zend_iterable(): Argument #2 ($arg2) must be of type ?iterable, string given
+
_(Z_EXPECTED_STRING_OR_NULL, "of type ?string") \
_(Z_EXPECTED_ARRAY, "of type array") \
_(Z_EXPECTED_ARRAY_OR_NULL, "of type ?array") \
+ _(Z_EXPECTED_ITERABLE, "of type iterable") \
+ _(Z_EXPECTED_ITERABLE_OR_NULL, "of type ?iterable") \
_(Z_EXPECTED_FUNC, "a valid callback") \
_(Z_EXPECTED_FUNC_OR_NULL, "a valid callback or null") \
_(Z_EXPECTED_RESOURCE, "of type resource") \
#define Z_PARAM_ARRAY_OR_OBJECT(dest) \
Z_PARAM_ARRAY_OR_OBJECT_EX(dest, 0, 0)
+#define Z_PARAM_ITERABLE_EX(dest, check_null) \
+ Z_PARAM_PROLOGUE(0, 0); \
+ if (UNEXPECTED(!zend_parse_arg_iterable(_arg, &dest, check_null))) { \
+ _expected_type = check_null ? Z_EXPECTED_ITERABLE_OR_NULL : Z_EXPECTED_ITERABLE; \
+ _error_code = ZPP_ERROR_WRONG_ARG; \
+ break; \
+ }
+
+#define Z_PARAM_ITERABLE(dest) \
+ Z_PARAM_ITERABLE_EX(dest, 0)
+
+#define Z_PARAM_ITERABLE_OR_NULL(dest) \
+ Z_PARAM_ITERABLE_EX(dest, 1)
+
/* old "b" */
#define Z_PARAM_BOOL_EX2(dest, is_null, check_null, deref, separate) \
Z_PARAM_PROLOGUE(deref, separate); \
return 1;
}
+static zend_always_inline bool zend_parse_arg_iterable(zval *arg, zval **dest, bool check_null)
+{
+ if (EXPECTED(zend_is_iterable(arg))) {
+ *dest = arg;
+ return 1;
+ }
+
+ if (check_null && EXPECTED(Z_TYPE_P(arg) == IS_NULL)) {
+ *dest = NULL;
+ return 1;
+ }
+
+ return 0;
+}
+
static zend_always_inline bool zend_parse_arg_array(zval *arg, zval **dest, bool check_null, bool or_object)
{
if (EXPECTED(Z_TYPE_P(arg) == IS_ARRAY) ||
return "IS_VOID";
case "callable":
return "IS_CALLABLE";
+ case "iterable":
+ return "IS_ITERABLE";
case "mixed":
return "IS_MIXED";
default:
}
/* }}} */
+/* TESTS Z_PARAM_ITERABLE and Z_PARAM_ITERABLE_OR_NULL */
+ZEND_FUNCTION(zend_iterable)
+{
+ zval *arg1, *arg2;
+
+ ZEND_PARSE_PARAMETERS_START(1, 2)
+ Z_PARAM_ITERABLE(arg1)
+ Z_PARAM_OPTIONAL
+ Z_PARAM_ITERABLE_OR_NULL(arg2)
+ ZEND_PARSE_PARAMETERS_END();
+}
+
static zend_object *zend_test_class_new(zend_class_entry *class_type) /* {{{ */ {
zend_object *obj = zend_objects_new(class_type);
object_properties_init(obj, class_type);
/** @param stdClass|string|null $param */
function zend_string_or_stdclass_or_null($param): stdClass|string|null {}
+
+function zend_iterable(iterable $arg1, ?iterable $arg2 = null): void {}
/* This is a generated file, edit the .stub.php file instead.
- * Stub hash: 82fd97d4985448884141842955a4bee2c90ba338 */
+ * Stub hash: 87c9d71b08c538c28b4f9bad01d7a7a3a3b191ef */
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_zend_test_array_return, 0, 0, IS_ARRAY, 0)
ZEND_END_ARG_INFO()
ZEND_ARG_INFO(0, param)
ZEND_END_ARG_INFO()
+ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_zend_iterable, 0, 1, IS_VOID, 0)
+ ZEND_ARG_TYPE_INFO(0, arg1, IS_ITERABLE, 0)
+ ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, arg2, IS_ITERABLE, 1, "null")
+ZEND_END_ARG_INFO()
+
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class__ZendTestClass_is_object, 0, 0, IS_LONG, 0)
ZEND_END_ARG_INFO()
ZEND_FUNCTION(zend_string_or_object_or_null);
ZEND_FUNCTION(zend_string_or_stdclass);
ZEND_FUNCTION(zend_string_or_stdclass_or_null);
+ZEND_FUNCTION(zend_iterable);
ZEND_METHOD(_ZendTestClass, is_object);
ZEND_METHOD(_ZendTestClass, __toString);
ZEND_METHOD(_ZendTestTrait, testMethod);
ZEND_FE(zend_string_or_object_or_null, arginfo_zend_string_or_object_or_null)
ZEND_FE(zend_string_or_stdclass, arginfo_zend_string_or_stdclass)
ZEND_FE(zend_string_or_stdclass_or_null, arginfo_zend_string_or_stdclass_or_null)
+ ZEND_FE(zend_iterable, arginfo_zend_iterable)
ZEND_FE_END
};