Skip to content

Commit d0ee2a8

Browse files
carusogabrielnikic
authored andcommitted
Add is_countable function
RFC: https://wiki.php.net/rfc/is-countable
1 parent 57896cf commit d0ee2a8

File tree

10 files changed

+96
-2
lines changed

10 files changed

+96
-2
lines changed

NEWS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,7 @@ PHP NEWS
171171
. Updated bundled libsqlite to 3.22.0. (cmb)
172172

173173
- Standard:
174+
. Added is_countable() function. (Gabriel Caruso)
174175
. Fixed bug #75916 (DNS_CAA record results contain garbage). (Mike,
175176
Philip Sharp)
176177
. Fixed unserialize(), to disable creation of unsupported data structures

UPGRADING

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -129,8 +129,10 @@ Intl:
129129
URestrictionLevel under
130130
http://icu-project.org/apiref/icu4c/uspoof_8h.html
131131

132-
SPL:
133-
. Added spl_object_id().
132+
Standard:
133+
. Added is_countable() function, to check whether a value may be passed to
134+
count().
135+
(RFC: https://wiki.php.net/rfc/is-countable)
134136

135137
========================================
136138
7. New Classes and Interfaces

Zend/zend_API.c

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4379,6 +4379,23 @@ ZEND_API zend_bool zend_is_iterable(zval *iterable) /* {{{ */
43794379
}
43804380
/* }}} */
43814381

4382+
ZEND_API zend_bool zend_is_countable(zval *countable) /* {{{ */
4383+
{
4384+
switch (Z_TYPE_P(countable)) {
4385+
case IS_ARRAY:
4386+
return 1;
4387+
case IS_OBJECT:
4388+
if (Z_OBJ_HT_P(countable)->count_elements) {
4389+
return 1;
4390+
}
4391+
4392+
return instanceof_function(Z_OBJCE_P(countable), zend_ce_countable);
4393+
default:
4394+
return 0;
4395+
}
4396+
}
4397+
/* }}} */
4398+
43824399
/*
43834400
* Local variables:
43844401
* tab-width: 4

Zend/zend_API.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -562,6 +562,8 @@ ZEND_API const char *zend_get_object_type(const zend_class_entry *ce);
562562

563563
ZEND_API zend_bool zend_is_iterable(zval *iterable);
564564

565+
ZEND_API zend_bool zend_is_countable(zval *countable);
566+
565567
#define add_method(arg, key, method) add_assoc_function((arg), (key), (method))
566568

567569
ZEND_API ZEND_FUNCTION(display_disabled_function);

ext/opcache/Optimizer/zend_func_info.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -610,6 +610,7 @@ static const func_info_t func_infos[] = {
610610
F0("is_object", MAY_BE_FALSE | MAY_BE_TRUE), // TODO: inline with support for incomplete class
611611
F0("is_scalar", MAY_BE_NULL | MAY_BE_FALSE | MAY_BE_TRUE),
612612
F0("is_callable", MAY_BE_NULL | MAY_BE_FALSE | MAY_BE_TRUE),
613+
F0("is_countable", MAY_BE_NULL | MAY_BE_FALSE | MAY_BE_TRUE),
613614
F0("pclose", MAY_BE_FALSE | MAY_BE_LONG),
614615
F1("popen", MAY_BE_NULL | MAY_BE_FALSE | MAY_BE_RESOURCE),
615616
F0("readfile", MAY_BE_FALSE | MAY_BE_LONG),

ext/standard/basic_functions.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2586,6 +2586,10 @@ ZEND_END_ARG_INFO()
25862586
ZEND_BEGIN_ARG_INFO_EX(arginfo_is_iterable, 0, 0, 1)
25872587
ZEND_ARG_INFO(0, var)
25882588
ZEND_END_ARG_INFO()
2589+
2590+
ZEND_BEGIN_ARG_INFO(arginfo_is_countable, 0)
2591+
ZEND_ARG_INFO(0, var)
2592+
ZEND_END_ARG_INFO()
25892593
/* }}} */
25902594
/* {{{ uniqid.c */
25912595
#ifdef HAVE_GETTIMEOFDAY
@@ -3111,6 +3115,7 @@ static const zend_function_entry basic_functions[] = { /* {{{ */
31113115
PHP_FE(is_scalar, arginfo_is_scalar)
31123116
PHP_FE(is_callable, arginfo_is_callable)
31133117
PHP_FE(is_iterable, arginfo_is_iterable)
3118+
PHP_FE(is_countable, arginfo_is_countable)
31143119

31153120
/* functions from file.c */
31163121
PHP_FE(pclose, arginfo_pclose)

ext/standard/php_type.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,5 +39,6 @@ PHP_FUNCTION(is_object);
3939
PHP_FUNCTION(is_scalar);
4040
PHP_FUNCTION(is_callable);
4141
PHP_FUNCTION(is_iterable);
42+
PHP_FUNCTION(is_countable);
4243

4344
#endif
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
--TEST--
2+
Test is_countable() function
3+
--CREDITS--
4+
Gabriel Caruso ([email protected])
5+
--FILE--
6+
<?php
7+
var_dump(is_countable(new class extends ArrayIterator {}));
8+
var_dump(is_countable((array) new stdClass()));
9+
var_dump(is_countable(new class implements Countable {
10+
public function count()
11+
{
12+
return count(1, 'foo');
13+
}
14+
}));
15+
?>
16+
--EXPECT--
17+
bool(true)
18+
bool(true)
19+
bool(true)
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
--TEST--
2+
Test is_countable() function
3+
--CREDITS--
4+
Gabriel Caruso ([email protected])
5+
--FILE--
6+
<?php
7+
var_dump(is_countable([1, 2, 3]));
8+
var_dump(is_countable((array) 1));
9+
var_dump(is_countable((object) ['foo', 'bar', 'baz']));
10+
var_dump(is_countable());
11+
12+
$foo = ['', []];
13+
14+
if (is_countable($foo)) {
15+
var_dump(count($foo));
16+
}
17+
18+
$bar = null;
19+
if (!is_countable($bar)) {
20+
count($bar);
21+
}
22+
?>
23+
--EXPECTF--
24+
bool(true)
25+
bool(true)
26+
bool(false)
27+
28+
Warning: is_countable() expects exactly 1 parameter, 0 given in %s on line %d
29+
NULL
30+
int(2)
31+
32+
Warning: count(): Parameter must be an array or an object that implements Countable in %s on line %d

ext/standard/type.c

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -395,6 +395,20 @@ PHP_FUNCTION(is_iterable)
395395
}
396396
/* }}} */
397397

398+
/* {{{ proto bool is_countable(mixed var)
399+
Returns true if var is countable (array or instance of Countable). */
400+
PHP_FUNCTION(is_countable)
401+
{
402+
zval *var;
403+
404+
ZEND_PARSE_PARAMETERS_START(1, 1)
405+
Z_PARAM_ZVAL(var)
406+
ZEND_PARSE_PARAMETERS_END();
407+
408+
RETURN_BOOL(zend_is_countable(var));
409+
}
410+
/* }}} */
411+
398412
/*
399413
* Local variables:
400414
* tab-width: 4

0 commit comments

Comments
 (0)