-
Notifications
You must be signed in to change notification settings - Fork 7.9k
Add is_list function #4886
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
Add is_list function #4886
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 |
---|---|---|
@@ -0,0 +1,94 @@ | ||
--TEST-- | ||
Test is_list() function | ||
--FILE-- | ||
<?php | ||
|
||
function test_is_list(string $desc, $val) : void { | ||
printf("%s: %s\n", $desc, is_list($val) ? "true" : "false"); | ||
} | ||
|
||
test_is_list("empty", []); | ||
test_is_list("one", [1]); | ||
test_is_list("two", [1,2]); | ||
test_is_list("three", [1,2,3]); | ||
test_is_list("four", [1,2,3,4]); | ||
test_is_list("ten", range(0, 10)); | ||
|
||
test_is_list("null", null); | ||
test_is_list("int", 123); | ||
test_is_list("float", 1.23); | ||
test_is_list("string", "string"); | ||
test_is_list("object", new stdclass); | ||
test_is_list("true", true); | ||
test_is_list("false", false); | ||
|
||
test_is_list("string key", ["a" => 1]); | ||
test_is_list("mixed keys", [0 => 0, "a" => 1]); | ||
test_is_list("ordered keys", [0 => 0, 1 => 1]); | ||
test_is_list("shuffled keys", [1 => 0, 0 => 1]); | ||
test_is_list("skipped keys", [0 => 0, 2 => 2]); | ||
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. I would also add a test to cover arrays with negative keys, e.g.: |
||
|
||
$arr = [1, 2, 3]; | ||
unset($arr[0]); | ||
test_is_list("unset first", $arr); | ||
|
||
$arr = [1, 2, 3]; | ||
unset($arr[1]); | ||
test_is_list("unset middle", $arr); | ||
|
||
$arr = [1, 2, 3]; | ||
unset($arr[2]); | ||
test_is_list("unset end", $arr); | ||
|
||
$arr = [1, "a" => "a", 2]; | ||
unset($arr["a"]); | ||
test_is_list("unset string key", $arr); | ||
|
||
$arr = [1 => 1, 0 => 0]; | ||
unset($arr[1]); | ||
test_is_list("unset into order", $arr); | ||
|
||
$arr = ["a" => 1]; | ||
unset($arr["a"]); | ||
test_is_list("unset to empty", $arr); | ||
|
||
$arr = [1, 2, 3]; | ||
$arr[] = 4; | ||
test_is_list("append implicit", $arr); | ||
|
||
$arr = [1, 2, 3]; | ||
$arr[3] = 4; | ||
test_is_list("append explicit", $arr); | ||
|
||
$arr = [1, 2, 3]; | ||
$arr[4] = 5; | ||
test_is_list("append with gap", $arr); | ||
|
||
--EXPECT-- | ||
empty: true | ||
one: true | ||
two: true | ||
three: true | ||
four: true | ||
ten: true | ||
null: false | ||
int: false | ||
float: false | ||
string: false | ||
object: false | ||
true: false | ||
false: false | ||
string key: false | ||
mixed keys: false | ||
ordered keys: true | ||
shuffled keys: false | ||
skipped keys: false | ||
unset first: false | ||
unset middle: false | ||
unset end: true | ||
unset string key: true | ||
unset into order: true | ||
unset to empty: true | ||
append implicit: true | ||
append explicit: true | ||
append with gap: false |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -289,6 +289,43 @@ PHP_FUNCTION(is_array) | |
} | ||
/* }}} */ | ||
|
||
/* {{{ proto bool is_list(mixed var) | ||
Returns true if variable is an array whose keys are all numeric, sequential, | ||
and start at 0 */ | ||
PHP_FUNCTION(is_list) | ||
{ | ||
zval *arg; | ||
zend_array *arrval; | ||
zend_ulong num_idx, expected_idx = 0; | ||
zend_string *str_idx; | ||
|
||
ZEND_PARSE_PARAMETERS_START(1, 1) | ||
Z_PARAM_ZVAL(arg) | ||
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. I think you could use 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. That would make the function throw an error when passed a non-array argument:
My intention was to make 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. @duskwuff AFAIK, you could also use the following if you want to achieve an ZEND_PARSE_PARAMS_START_EX(ZEND_PARSE_PARAMS_QUIET, 1, 1)
// ... (Although I would also prefer constraining the parameter type to 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. @duskwuff, ah, I see. Thanks. |
||
ZEND_PARSE_PARAMETERS_END(); | ||
|
||
if (Z_TYPE_P(arg) != IS_ARRAY) | ||
RETURN_FALSE; | ||
|
||
arrval = Z_ARRVAL_P(arg); | ||
|
||
/* Empty arrays are lists */ | ||
if (zend_hash_num_elements(arrval) == 0) | ||
RETURN_TRUE; | ||
|
||
/* Packed arrays are lists */ | ||
if (HT_IS_PACKED(arrval) && HT_IS_WITHOUT_HOLES(arrval)) | ||
RETURN_TRUE; | ||
|
||
/* Check if the list could theoretically be repacked */ | ||
ZEND_HASH_FOREACH_KEY(arrval, num_idx, str_idx) { | ||
if (str_idx != NULL || num_idx != expected_idx++) | ||
RETURN_FALSE; | ||
} ZEND_HASH_FOREACH_END(); | ||
|
||
RETURN_TRUE; | ||
} | ||
/* }}} */ | ||
|
||
/* {{{ proto bool is_object(mixed var) | ||
Returns true if variable is an object | ||
Warning: This function is special-cased by zend_compile.c and so is usually bypassed */ | ||
|
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.
php has changed to put stubs in basic_functions.stub.php - the basic_functions_arginfo.h file is automatically regenerated from this during
make