]> granicus.if.org Git - php/commitdiff
Add Z_PARAM_ITERABLE and co
authorLevi Morrison <levim@php.net>
Thu, 3 Sep 2020 13:03:12 +0000 (07:03 -0600)
committerLevi Morrison <levim@php.net>
Thu, 3 Sep 2020 13:03:12 +0000 (07:03 -0600)
Zend/tests/iterable_or_null.phpt [new file with mode: 0644]
Zend/zend_API.h
build/gen_stub.php
ext/zend_test/test.c
ext/zend_test/test.stub.php
ext/zend_test/test_arginfo.h

diff --git a/Zend/tests/iterable_or_null.phpt b/Zend/tests/iterable_or_null.phpt
new file mode 100644 (file)
index 0000000..9f798af
--- /dev/null
@@ -0,0 +1,49 @@
+--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
+
index 70e757c1bb630520aac1b1dfdc9d0863cef4a269..a81a43f2314de40021c96ebc136ad4bdac21f743 100644 (file)
@@ -1209,6 +1209,8 @@ static zend_always_inline zval *zend_try_array_init(zval *zv)
        _(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") \
@@ -1373,6 +1375,20 @@ ZEND_API ZEND_COLD void zend_argument_value_error(uint32_t arg_num, const char *
 #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); \
@@ -1903,6 +1919,21 @@ static zend_always_inline bool zend_parse_arg_path(zval *arg, char **dest, size_
        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) ||
index 214d1f563e737727aee315310f006477b7c19e78..de2d3b144b06d252a1f5fed910bf2bebd5492028 100755 (executable)
@@ -112,6 +112,8 @@ class SimpleType {
             return "IS_VOID";
         case "callable":
             return "IS_CALLABLE";
+        case "iterable":
+            return "IS_ITERABLE";
         case "mixed":
             return "IS_MIXED";
         default:
index 2d91543cf1f66fa46a16a548cf19e97dc54d1b48..18e744331339bb65ae88aa70bac255535e9780fa 100644 (file)
@@ -221,6 +221,18 @@ ZEND_FUNCTION(zend_string_or_stdclass_or_null)
 }
 /* }}} */
 
+/* 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);
index cc4a561f542371aeba9ad149fa715f0a1880f30b..1dd0cfec4e5b179c1b2f9bce898133d5a11d4dd7 100644 (file)
@@ -39,3 +39,5 @@ function zend_string_or_stdclass($param): stdClass|string {}
 
 /** @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 {}
index ae7cd77b587c8c40add3a57ae94a10ebaa5ee34a..bd8d477b42b165c3a9e439b7de4186f88964fc51 100644 (file)
@@ -1,5 +1,5 @@
 /* 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()
@@ -46,6 +46,11 @@ ZEND_BEGIN_ARG_WITH_RETURN_OBJ_TYPE_MASK_EX(arginfo_zend_string_or_stdclass_or_n
        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()
 
@@ -68,6 +73,7 @@ ZEND_FUNCTION(zend_string_or_object);
 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);
@@ -86,6 +92,7 @@ static const zend_function_entry ext_functions[] = {
        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
 };