-
Notifications
You must be signed in to change notification settings - Fork 7.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[RFC] Add is_countable function #3026
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4379,6 +4379,23 @@ ZEND_API zend_bool zend_is_iterable(zval *iterable) /* {{{ */ | |
} | ||
/* }}} */ | ||
|
||
ZEND_API zend_bool zend_is_countable(zval *countable) /* {{{ */ | ||
{ | ||
switch (Z_TYPE_P(countable)) { | ||
case IS_ARRAY: | ||
return 1; | ||
case IS_OBJECT: | ||
if (Z_OBJ_HT_P(countable)->count_elements) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In which case it will be There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @rentalhost it will be true for extension defined objects that implements their own countable technique There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @rentalhost Like @KalleZ said. Also, see @duncan3dc's comment and #2206. Ref: http://www.phpinternalsbook.com/classes_objects/object_handlers.html#c.count_elements |
||
return 1; | ||
} | ||
|
||
return instanceof_function(Z_OBJCE_P(countable), zend_ce_countable); | ||
default: | ||
return 0; | ||
} | ||
} | ||
/* }}} */ | ||
|
||
/* | ||
* Local variables: | ||
* tab-width: 4 | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
--TEST-- | ||
Test is_countable() function | ||
--CREDITS-- | ||
Gabriel Caruso (carusogabriel34@gmail.com) | ||
--FILE-- | ||
<?php | ||
var_dump(is_countable(new class extends ArrayIterator {})); | ||
var_dump(is_countable((array) new stdClass())); | ||
var_dump(is_countable(new class implements Countable { | ||
public function count() | ||
{ | ||
return count(1, 'foo'); | ||
} | ||
})); | ||
?> | ||
--EXPECT-- | ||
bool(true) | ||
bool(true) | ||
bool(true) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
--TEST-- | ||
Test is_countable() function | ||
--CREDITS-- | ||
Gabriel Caruso (carusogabriel34@gmail.com) | ||
--FILE-- | ||
<?php | ||
var_dump(is_countable([1, 2, 3])); | ||
var_dump(is_countable((array) 1)); | ||
var_dump(is_countable((object) ['foo', 'bar', 'baz'])); | ||
var_dump(is_countable()); | ||
|
||
$foo = ['', []]; | ||
|
||
if (is_countable($foo)) { | ||
var_dump(count($foo)); | ||
} | ||
|
||
$bar = null; | ||
if (!is_countable($bar)) { | ||
count($bar); | ||
} | ||
?> | ||
--EXPECTF-- | ||
bool(true) | ||
bool(true) | ||
bool(false) | ||
|
||
Warning: is_countable() expects exactly 1 parameter, 0 given in %s on line %d | ||
NULL | ||
int(2) | ||
|
||
Warning: count(): Parameter must be an array or an object that implements Countable in %s on line %d |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If possible we should make this
zval const *
. At a glance it depends ifinstanceof_function
and related calls are const or not.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
By convention, zvals are never passed by const pointer.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So it should stay as it is?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The convention likely stems from the days where our zvals directly contained reference counting information. Passing such values by const pointer would prevent making copies on reference counted types, so it wasn't done.
I would prefer it to be const - maybe we should wait for someone else (maybe @dstogov?) to chime in.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we please move this discussion elsewhere (i.e. php.internals) and focus on this patch? We currently have two discussions here both unrelated to the patch itself. Thanks. 👍
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@Majkl578 You misunderstand. The const discussion is about the patch.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This really sounds like a global issue for all zvals, not just this patch. Trying to mitigate this convention is out of scope here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is my opinion.: it appears
instanceof_function
takes its parameters by pointer to const andZ_TYPE_P
should be const correct as well. This function should take its parameter by pointer to const because we have verified here, today, that it is const correct. It is easier to do this now than later. No other functions need to be adjusted for this function to work with const parameters. As such I believe this is in scope for this PR. If other functions would have to be adjust for it to work then it would be out of scope.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@morrisonlevi To avoid this discution on to be const or not to be, should I move this
switch
to the function declaration, intype.c
like #2206?Also, may I ask you something? What are the difference between have the function here in
Zend_api.c
or there intype.c
?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Having it in the API means it can be called from other places in the C code. I think it belongs there - I would not move it inline like the other PR.